在我们开始之前,让我们先呈现他们在论文中写的算法的伪代码:
procedure AdaptiveThreshold(in,out,w,h)
1: for i = 0 to w do
2: sum ← 0
3: for j = 0 to h do
4: sum ← sum+in[i, j]
5: if i = 0 then
6: intImg[i, j] ← sum
7: else
8: intImg[i, j] ← intImg[i−1, j] +sum
9: end if
10: end for
11: end for
12: for i = 0 to w do
13: for j = 0 to h do
14: x1 ← i−s/2 {border checking is not shown}
15: x2 ← i+s/2
16: y1 ← j −s/2
17: y2 ← j +s/2
18: count ← (x2−x1)×(y2−y1)
19: sum ← intImg[x2,y2]−intImg[x2,y1−1]−intImg[x1−1,y2] +intImg[x1−1,y1−1]
20: if (in[i, j]×count) ≤ (sum×(100−t)/100) then
21: out[i, j] ← 0
22: else
23: out[i, j] ← 255
24: end if
25: end for
26: end for
intImg
是输入图像的积分图,用于阈值处理,假设为灰度图。
我已经成功地实现了这个算法,让我们来谈谈你的疑惑。
那么count
是什么呢?如果它是窗口中的像素数,为什么根据算法它不是3*3=9而是2*2=4呢?
在论文中存在一个未明确说明的假设。 s
的值必须是奇数,并且窗口应该如下:
x1 = i - floor(s/2)
x2 = i + floor(s/2)
y1 = j - floor(s/2)
y2 = j + floor(s/2)
count
是窗口中像素的总数,但您还需要确保不超出边界。您那里肯定应该是一个 3 x 3 的窗口,因此
s=3
,而不是2。现在,如果
s=3
,但如果我们选择
i=0,j=0
,我们将得到负值
x和
y值。我们不能这样做,所以在
i = 0, j = 0
处居中的这个 3 x 3 窗口内的有效像素总数为 4,因此
count = 4
。对于位于图像范围内的窗口,则
count
为 9。
Further, why is the original value of the pixel multiplied by the count? The paper says that the value is compared to the average value of surrounding pixels, why it isn't:
in[i,j] <= (sum/count) * ((100 - t) / 100)
then?
您所查看的条件在算法的第20行:
您所查看的条件在算法的第20行:
20: (in[i, j]×count) ≤ (sum×(100−t)/100)
我们关注
in[i,j]*count
的原因是因为我们假设
in[i,j]
是
s x s
窗口中的
平均强度。 因此,如果我们检查了一个
s x s
窗口并将所有强度相加,这等于
in[i,j] x count
。该算法非常巧妙。基本上,我们比较
s x s
窗口内假定的平均强度(
in[i,j] x count
)和如果这个值小于此
s x s
窗口内
实际平均强度的%(
sum x ((100-t)/100)
),则输出设置为黑色。如果它更大,则输出设置为白色。不过,您已经优美地表达应写成以下内容:
in[i,j] <= (sum/count) * ((100 - t) / 100)
这与第20行本质上相同,但你将方程式的两侧除以
count
,所以它仍然是相同的表达式。我会说这明确说明了我以上所说的。乘以
count
的操作肯定会令人困惑,所以你所写的更有意义。
因此,你只是以不同的方式看待它,这完全没有问题!所以回答你的问题,你所陈述的肯定是正确的,并且等同于实际算法中所见到的表达式。
希望对你有所帮助!
s = 2
?看起来你想要s = 3
和s/2 = 1.5
。对于这种类型的问题,非整数的s/2
可能是一个问题,所以我能理解你的担忧。实际上,也许算法假定s
总是一个偶数,而你的例子并不是。在这种情况下,有界区域可能会排除点(x2,y2)
处的像素。 - Brent Bradburn