因此,执行剪辑限制的方式如下:
- 概率密度函数( PDF )是为每个可能的像素强度计算的,假设我们有一个8位的图像,所以PDF是一个索引0到255的数组。PDF是通过计算具有该强度的图像中的像素数来计算的,因此,例如,PDF(强度= 0) = 26意味着图像中有26个像素的亮度为0。
- 一旦计算了PDF,代码就会循环遍历PDF中的每个元素,并确定该PDF元素是否大于clipLimit。例如,假设clipLimit是4,我们从PDF( 0 ) = 26开始,它大于4。因此,代码“剪辑”了
clipped = clipped + pdf[i] - clipLimit;在4处的亮度为0的像素计数,其中剪裁开始于0。然后剪裁=0+ 26 -4= 22.对于PDF(强度= 1)、PDF(强度= 2)、.、PDF(强度= 255),代码继续这样做。最后,PDF中没有一个单独的元素比clipLimit更大,多余的像素数已经存储在被剪裁的变量中。(就像fmw42所说的)。 - 然后,裁剪像素的数量被重新均匀地分布在数组PDF中。例如,假设clipped = 128,那么PDF的其他元素大约都会得到+1像素的计数。因此,如果PDF(0) = 4,PDF(1) = 2,PDF(2) =0,那么在重新分发后,它将是PDF(0) = 4+1,PDF(1) = 2,PDF(2) = 0+1。注意,在重新分配后,以前位于最大值的一些像素( clipLimit )会被稍微向上推到clipLimit上。
在维基百科中,clipLimit通常被设置在3到4之间。当剪辑限制被实现时,直方图中任何元素的最大值都是有限的,因此直方图中任意两个相邻元素之间的最大斜率(即强度变化)是有限的。
- 一个不现实但很有帮助的练习是,想象一下1920年x 1080像素的图像中的所有像素都是强度1,所以PDF的开头是PDF( 0 ) = 0,PDF(1) = 2073600,而PDF的其余元素是0。然后,得到的斜率=( 2073600 ~0)/(1-0)=2073600。
- 但是,现在想象一下,对于同一幅图像,我们设置一个4的clipLimit,并为整个图像设置一个直方图。裁剪后的PDF为: PDF(0) = 0,PDF(1) = 4,PDF(2) = 0,以此类推。剪裁后的最大斜率为(4-0)/(1-0) = 4,远远小于2073600。重新分配后,每个直方图bin得到大约8100像素,因此PDF(0) = 8100,PDF(1) = 8104,PDF(2) = 8100,等等。剪裁和再分布后的最大斜率为(8104-8100)/(1-0) = 4。
至于你的问题,PDF的总和的确是1,但这里的PDF阵列储存了数,即PDF的分子。因此,对于大小为1920 x 1080的图像,如果实际PDF是
- 概率(强度= 0) = 4/(1920x1080) = 4/2073600
- P(强度= 1) = 2/2073600
- P(强度= 2) = 0/2073600,那么这些分数的之和确实是1。这个在OpenCV源代码中实现的概率密度函数在数组PDF中显示为:
- PDF(0) =4
- PDF(1) =2
- PDF(2) =0,这些元素在没有分母的情况下不能和为1。
有关代码的实现,请参阅OpenCV源代码。作为脚注,我对重新分配的实施作了一些简化,但希望它更容易理解。