布拉德利自适应阈值 -- 困惑(问题)

3

我有一些关于Bradley自适应阈值算法实现的问题,可能很蠢。我已经阅读了相关论文http://people.scs.carleton.ca:8008/~roth/iit-publications-iti/docs/gerh-50002.pdf,但仍感到有点困惑。主要是关于这个声明:

if ((in[i,j]*count) ≤ (sum*(100−t)/100)) then

Let's assume that we have this input:

            width, i
            [0] [1] [2]
           +---+---+---+
height [0] | 1 | 2 | 2 |
j          +---+---+---+
       [1] | 3 | 4 | 3 |
           +---+---+---+
       [2] | 5 | 3 | 2 |
           +---+---+---+

假设:

s = 2
s/2 = 1
t = 15
i = 1
j = 1 (we are at the center pixel)

那么这意味着我们有一个3x3的窗口,对吧?然后:
x1 = 0, x2 = 2, y1 = 0, y2 = 2

"count"是什么?如果它是窗口中像素的数量,为什么根据算法它是2*2=4而不是3*3=9?此外,为什么原始像素值要乘以"count"?

论文中说,该值与周围像素的平均值进行比较,为什么不是?

in[i,j] <= (sum/count) * ((100 - t) / 100)

那么呢?

有人可以给我解释一下吗?这可能是一个非常愚蠢的问题,但我想不出来。


1
请在选择标签时更加注意。您选择了“image”和“Processing”,而没有费心去查看它们的含义。第一个是关于图像文件的,第二个是针对编程语言Processing的。您应该使用“image-processing”标签。 - Mike 'Pomax' Kamermans
你为什么要说s = 2?看起来你想要s = 3s/2 = 1.5。对于这种类型的问题,非整数的s/2可能是一个问题,所以我能理解你的担忧。实际上,也许算法假定s总是一个偶数,而你的例子并不是。在这种情况下,有界区域可能会排除(x2,y2)处的像素。 - Brent Bradburn
1个回答

3

在我们开始之前,让我们先呈现他们在论文中写的算法的伪代码:

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,我们将得到负值xy值。我们不能这样做,所以在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 的操作肯定会令人困惑,所以你所写的更有意义。
因此,你只是以不同的方式看待它,这完全没有问题!所以回答你的问题,你所陈述的肯定是正确的,并且等同于实际算法中所见到的表达式。
希望对你有所帮助!

1
太棒了!非常感谢,我现在明白了。 :) - equinox

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接