使用python提取二进制图像中的连接像素

Posted

技术标签:

【中文标题】使用python提取二进制图像中的连接像素【英文标题】:Extract connected pixels in a binary image using python 【发布时间】:2016-05-15 10:14:47 【问题描述】:

我有一个二值图像 - 黑色像素 (0) 和白色 (1)。 我想编写一个函数来获取图像和黑色像素的位置 - x 和 y 并返回与给定像素连接(连接 = 8 连接)的所有像素的位置,以及所有像素的总计数连接的像素。 例如,如果这是我的图像:

1 1 1 1
1 0 0 1
1 1 0 1
1 1 1 1

我给函数像素 (1,1) 的输出将是:

count=3
x=[1,2,2]
y=[1,1,2]

这就是我所做的:

def find_connectivity(img,i,j,count,x,y):
    sys.setrecursionlimit(50000)
    if(img[i][j]==0):
        img[i][j]=2

        count=count+1
        xx=x
        yy=y
        xx=xx.append(i)
        yy=yy.append(j)
    rows=[-1, 0 ,1]
    cols=[-1, 0 ,1]
    for r in rows:
        for c in cols:
            if(img[i+r][j+c]==0):
                count,x,y= find_connectivity(img,i+r,j+c,count,x,y)
    return count,x,y

当我初始计数为 0,x 和 y 为 []。 例如在前面的例子中,对函数的调用是:

[count,x,y]=find_connectivity(img,1,1,0,[],[])

现在,此功能适用于相当大的群体 (5300+) - 但除此之外,我收到一条消息“python.exe 已停止工作”。 带有以下错误详细信息:

Application Timestamp:  5665e7c3
Fault Module Name:  ntdll.dll
Fault Module Version:   6.1.7601.19045
Fault Module Timestamp: 56259295
Exception Code: c00000fd
Exception Offset:   00000000000510a1
OS Version: 6.1.7601.2.1.0.256.48
Locale ID:  1033
Additional Information 1:   2a7e
Additional Information 2:   2a7edff1635197ae43266443b8d73ae8
Additional Information 3:   6edf
Additional Information 4:   6edf0945fe78222ec4c56cecff238926 

我猜是因为递归 - 但我想不出另一种有效的方法。

openCV/numpy/other 中是否有可以帮助我的函数? 或者有没有办法通过递归来防止崩溃?

谢谢!

【问题讨论】:

嘿,2 是否表示您访问过该节点?如果你知道怎么做,我建议你尝试广度优先搜索,它会运行得更快。 为什么不使用 OpenCV connectedComponents 或 findContours?没有必要重新发明*** 【参考方案1】:

你应该像下面这样使用Breadth-first search

import queue
def find_connectivity(img, i, j):
    dx = [0, 0, 1, 1, 1, -1, -1, -1]
    dy = [1, -1, 0, 1, -1, 0, 1, -1]
    x = []
    y = []
    q = queue.Queue()
    if img[i][j] == 0:
        q.put((i, j))
    while q.empty() == False:
        u, v = q.get()
        x.append(u)
        y.append(v)
        for k in range(8):
            xx = u + dx[k]
            yy = v + dy[k]
            if img[xx][yy] == 0:
                img[xx][yy] = 2
                q.put((xx, yy))
    return x, y

【讨论】:

您的解决方案几乎是完美的,您只需要记住每次 img[i][j] 的值等于 0 时都要更改它的值 - 否则 while 循环将是无限的。无论如何,非常感谢! 对不起,我忘记了。我已经解决了这个问题。【参考方案2】:

如果您对轮廓不感兴趣,您可以简单地使用种子填充算法。另见区域增长,区域填充

将您的点用作种子点,并使用 0 或 1 以外的某个值填充该区域。使用该新值计算像素或列出它们以获得数字及其坐标。

http://docs.opencv.org/2.4/modules/imgproc/doc/miscellaneous_transformations.html 请参阅 floodFill。

【讨论】:

以上是关于使用python提取二进制图像中的连接像素的主要内容,如果未能解决你的问题,请参考以下文章

如何访问二进制 Mat 图像中的像素值?

在 python 上比较图像并允许像素偏移差异

检测二进制图像中的高密度像素区域

OpenCV 中的连接组件

在MATLAB中找出二进制图像中白色区域的像素数以及原始图像中ROI的像素数

使用 OpenCV 获取二进制图像中白色像素数量的最快方法