Python Bradley自适应阈值算法

Python Bradley自适应阈值算法,python,python-imaging-library,adaptive-threshold,Python,Python Imaging Library,Adaptive Threshold,我目前正致力于实现一种称为“Bradley Adaptive thresholding”的阈值算法 为了解决如何实现这个算法,我主要关注了两个链接。我还成功地实现了另外两种阈值算法,主要是和 以下是创建Bradley自适应阈值算法时我一直遵循的两个链接 这是我在Python中运行算法并保存图像的源代码部分。我使用Python图像库,没有其他工具来完成我想做的事情 def get_bradley_binary(inp_im): w, h = inp_im.size s, t =

我目前正致力于实现一种称为“Bradley Adaptive thresholding”的阈值算法

为了解决如何实现这个算法,我主要关注了两个链接。我还成功地实现了另外两种阈值算法,主要是和

以下是创建
Bradley自适应阈值算法时我一直遵循的两个链接

这是我在
Python
中运行算法并保存图像的源代码部分。我使用
Python图像库
,没有其他工具来完成我想做的事情

def get_bradley_binary(inp_im):
    w, h = inp_im.size
    s, t = (w / 8, 0.15)

    int_im = Image.new('L', (w, h))
    out_im = Image.new('L', (w, h))

    for i in range(w):
        summ = 0
        for j in range(h):
            index = j * w + i

            summ += get_pixel_offs(inp_im, index)

            if i == 0:
                set_pixel_offs(int_im, index, summ)
            else:
                temp = get_pixel_offs(int_im, index - 1) + summ
                set_pixel_offs(int_im, index, temp)

    for i in range(w):
        for j in range(h):
            index = j * w + i

            x1,x2,y1,y2 = (i-s/2, i+s/2, j-s/2, j+s/2)

            x1 = 0 if x1 < 0 else x1
            x2 = w - 1 if x2 >= w else x2
            y1 = 0 if y1 < 0 else y1
            y2 = h - 1 if y2 >= h else y2

            count = (x2 - x1) * (y2 - y1)

            a1 = get_pixel_offs(int_im, y2 * w + x2)
            a2 = get_pixel_offs(int_im, y1 * w + x2)
            a3 = get_pixel_offs(int_im, y2 * w + x1)
            a4 = get_pixel_offs(int_im, y1 * w + x1)

            summ = a1 - a2 - a3 + a4

            temp = get_pixel_offs(inp_im, index)
            if temp * count < summ * (1.0 - t):
                set_pixel_offs(out_im, index, 0)
            else:
                set_pixel_offs(out_im, index, 255)

    return out_im
最后,这里是输入和输出图像。这些图像与我提供给您的第一个链接中原始研究论文中使用的图像相同。注意:输出图像几乎完全是白色的,可能很难看到,但我还是提供了它,以防有人真的想要它作为参考


您不能以当前的方式使用PIL创建整数映像,因为您正在打包数据的映像不能接受超过255的值。积分图像中的值变得非常大,因为它们是上方和左侧像素的总和(请参阅白皮书第3页,如下)

它们将比255大得多,因此您需要每像素32位来存储它们

您可以通过在“L”模式下创建一个PIL图像,然后将像素设置为1000000或某个较大的数字来测试这一点。然后,当您读回该值时,它将返回255

>>> from PIL import Image
>>> img = Image.new('L', (100,100))
>>> img.putpixel((0,0), 100000)
>>> print(list(img.getdata())[0])
255
编辑:阅读PIL文档后,如果您在“I”模式而不是“L”模式下创建完整图像,则可以使用PIL。这应该提供每像素32位

因此,我推荐Numpy而不是PIL

下面是使用Numpy而不是PIL重写阈值函数,我得到了正确/预期的结果。请注意,我使用uint32数组创建了我的整数图像。我在Github上使用了与您翻译时使用的完全相同的C示例:

import numpy as np

def adaptive_thresh(input_img):

    h, w = input_img.shape

    S = w/8
    s2 = S/2
    T = 15.0

    #integral img
    int_img = np.zeros_like(input_img, dtype=np.uint32)
    for col in range(w):
        for row in range(h):
            int_img[row,col] = input_img[0:row,0:col].sum()

    #output img
    out_img = np.zeros_like(input_img)    

    for col in range(w):
        for row in range(h):
            #SxS region
            y0 = max(row-s2, 0)
            y1 = min(row+s2, h-1)
            x0 = max(col-s2, 0)
            x1 = min(col+s2, w-1)

            count = (y1-y0)*(x1-x0)

            sum_ = int_img[y1, x1]-int_img[y0, x1]-int_img[y1, x0]+int_img[y0, x0]

            if input_img[row, col]*count < sum_*(100.-T)/100.:
                out_img[row,col] = 0
            else:
                out_img[row,col] = 255

    return out_img
将numpy导入为np
def自适应阈值(输入图像):
h、 w=输入形状
S=w/8
s2=S/2
T=15.0
#积分img
int\u img=np.zero\u like(input\u img,dtype=np.uint32)
对于范围内的列(w):
对于范围(h)中的行:
int_img[row,col]=input_img[0:row,0:col].sum()
#输出img
out\u img=np.类零(input\u img)
对于范围内的列(w):
对于范围(h)中的行:
#SxS区
y0=最大值(第s2行,0)
y1=最小值(行+s2,h-1)
x0=最大值(col-s2,0)
x1=最小值(col+s2,w-1)
计数=(y1-y0)*(x1-x0)
求和=整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数整数
如果输入[row,col]*计数<总和(100.-T)/100:
out\u img[行,列]=0
其他:
out\u img[行,列]=255
退场

我试图重新实现该算法,但没有使用1D数组,也没有切换到2D numpy数组,以更好地符合实际论文中提到的原始算法。我用它来研究使用深度学习模型的数据分析。这就是实现:

import numpy, gc
from ctypes import *    

def adaptive_threshold(self):
    gc.collect()
    gc.disable()

    w, h = self._image.width, self._image.height
    s, t = w//8, 0.15
    summ = c_uint32(0)
    count = c_uint32(0)
    pixels = self._pixels

    int_img = numpy.ndarray(shape=(w, h), dtype=c_int64)

    for i in range(w):
        summ.value = 0
        for j in range(h):
            summ.value += sum(pixels[i, j])
            if i != 0:
                int_img[i, j] = int_img[i - 1, j] + summ.value
            else:
                int_img[i, j] = summ.value


    x1, x2, y1, y2 = c_uint16(0), c_uint16(0), c_uint16(0), c_uint16(0)
    for i in range(w):
        for j in range(h):
            x1.value = max(i - s // 2, 0)
            x2.value = min(i + s // 2, w - 1)
            y1.value = max(j - s // 2, 0)
            y2.value = min(j + s // 2, h - 1)

            count.value = (x2.value - x1.value) * (y2.value - y1.value)

            summ.value = int_img[x2.value][y2.value] - int_img[x1.value][y2.value] - \
                int_img[x2.value][y1.value] + int_img[x1.value][y1.value]

            if sum(pixels[i, j]) * count.value < summ.value * (1.0 - t):
                pixels[i, j] = 0, 0, 0
            else:
                pixels[i, j] = 255, 255, 255

    gc.enable()
其中“Image”是open Image的一个实例

对于像1200x700这样被认为是高清的图像,它需要几秒钟的时间,但在样本图像上只需要几秒钟的时间。


希望这对其他人有所帮助。

什么不起作用,正确的输出图像生成?你有任何非视觉测试吗?是的,正确的输出图像生成不起作用,我使用了研究论文用于测试的完全相同的图像,输出图像是完全白色的,看起来与研究论文的输出图像不一样。至于非视觉测试,我不知道你的意思。我花了一段时间才接受这个答案,因为我一直很忙,但是是的!我没有意识到他们增加了超过255的值,积分图像只是数据的抽象表示,非常感谢!
import numpy, gc
from ctypes import *    

def adaptive_threshold(self):
    gc.collect()
    gc.disable()

    w, h = self._image.width, self._image.height
    s, t = w//8, 0.15
    summ = c_uint32(0)
    count = c_uint32(0)
    pixels = self._pixels

    int_img = numpy.ndarray(shape=(w, h), dtype=c_int64)

    for i in range(w):
        summ.value = 0
        for j in range(h):
            summ.value += sum(pixels[i, j])
            if i != 0:
                int_img[i, j] = int_img[i - 1, j] + summ.value
            else:
                int_img[i, j] = summ.value


    x1, x2, y1, y2 = c_uint16(0), c_uint16(0), c_uint16(0), c_uint16(0)
    for i in range(w):
        for j in range(h):
            x1.value = max(i - s // 2, 0)
            x2.value = min(i + s // 2, w - 1)
            y1.value = max(j - s // 2, 0)
            y2.value = min(j + s // 2, h - 1)

            count.value = (x2.value - x1.value) * (y2.value - y1.value)

            summ.value = int_img[x2.value][y2.value] - int_img[x1.value][y2.value] - \
                int_img[x2.value][y1.value] + int_img[x1.value][y1.value]

            if sum(pixels[i, j]) * count.value < summ.value * (1.0 - t):
                pixels[i, j] = 0, 0, 0
            else:
                pixels[i, j] = 255, 255, 255

    gc.enable()
Image.convert('RGB')