在没有 scipy 的情况下对二值化图像中的对象进行计数
Count objects in a binarized image without scipy
我正在尝试计算我已经二值化的图像中对象的数量,但是,我不允许使用 scipy 或 numpy 包,因此我不能使用 scipy.ndimage.label
,有什么想法吗?我尝试计算了 80 多个对象,但只有 13 个(用 scipy 计算)
def label(img):
n=1
for i in range(h):
for j in range(c):
if img[i][j]==255:
if img[i-1][j]!=0 and img[i-1][j]!=255:
img[i][j]=img[i-1][j]
elif img[i+1][j]!=0 and img[i+1][j]!=255:
img[i][j]=img[i-1][j]
elif img[i][j+1]!=0 and img[i][j+1]!=255:
img[i][j]=img[i][j+1]
elif img[i][j-1]!=0 and img[i][j-1]!=255:
img[i][j]=img[i][j-1]
else:
img[i][j]=n
if img[i-1][j]!=0:
img[i-1][j]=img[i][j]
if img[i+1][j]!=0:
img[i+1][j]=img[i][j]
if img[i][j+1]!=0:
img[i][j+1]=img[i][j]
if img[i][j-1]!=0:
img[i][j-1]=img[i][j]
n+=1
elif img[i][j]!=0:
if img[i-1][j]!=0:
img[i-1][j]=img[i][j]
if img[i+1][j]!=0:
img[i+1][j]=img[i][j]
if img[i][j+1]!=0:
img[i][j+1]=img[i][j]
if img[i][j-1]!=0:
img[i][j-1]=img[i][j]
return img,n
你会想要像 https://codereview.stackexchange.com/questions/148897/floodfill-algorithm, which implements https://en.wikipedia.org/wiki/Flood_fill 这样的东西。
如果可行,它非常适合 numba 或 cython。
也许您可以使用 OpenCV,它已经提供了 floodfill:https://docs.opencv.org/3.4/d7/d1b/group__imgproc__misc.html#gaf1f55a048f8a45bc3383586e80b1f0d0.
假设您已二值化,因此背景为颜色 1,对象为颜色 0。设置 c = 2
,扫描零像素,并用颜色 c
对其进行填充。
现在增加 c
,扫描零,填充,起泡沫,冲洗,重复。
您最终会得到带有不同颜色的每个对象,因此您可以将其用作隔离遮罩。
不同的颜色在调试过程中非常有用,但如果您只想计数,当然三种颜色就足够了(甚至两种)。
最终位图在双色情况下统一为背景色。
使用 4 元素 Von Neumann neighborhood versus an 8-element neighborhood 会对最终结果产生很大影响。
通过 8 元素设置中的对角线连通性,绘制 "leak" 更容易。
进行边缘检测和加厚有助于减少不必要的颜色泄漏。
我正在尝试计算我已经二值化的图像中对象的数量,但是,我不允许使用 scipy 或 numpy 包,因此我不能使用 scipy.ndimage.label
,有什么想法吗?我尝试计算了 80 多个对象,但只有 13 个(用 scipy 计算)
def label(img):
n=1
for i in range(h):
for j in range(c):
if img[i][j]==255:
if img[i-1][j]!=0 and img[i-1][j]!=255:
img[i][j]=img[i-1][j]
elif img[i+1][j]!=0 and img[i+1][j]!=255:
img[i][j]=img[i-1][j]
elif img[i][j+1]!=0 and img[i][j+1]!=255:
img[i][j]=img[i][j+1]
elif img[i][j-1]!=0 and img[i][j-1]!=255:
img[i][j]=img[i][j-1]
else:
img[i][j]=n
if img[i-1][j]!=0:
img[i-1][j]=img[i][j]
if img[i+1][j]!=0:
img[i+1][j]=img[i][j]
if img[i][j+1]!=0:
img[i][j+1]=img[i][j]
if img[i][j-1]!=0:
img[i][j-1]=img[i][j]
n+=1
elif img[i][j]!=0:
if img[i-1][j]!=0:
img[i-1][j]=img[i][j]
if img[i+1][j]!=0:
img[i+1][j]=img[i][j]
if img[i][j+1]!=0:
img[i][j+1]=img[i][j]
if img[i][j-1]!=0:
img[i][j-1]=img[i][j]
return img,n
你会想要像 https://codereview.stackexchange.com/questions/148897/floodfill-algorithm, which implements https://en.wikipedia.org/wiki/Flood_fill 这样的东西。 如果可行,它非常适合 numba 或 cython。
也许您可以使用 OpenCV,它已经提供了 floodfill:https://docs.opencv.org/3.4/d7/d1b/group__imgproc__misc.html#gaf1f55a048f8a45bc3383586e80b1f0d0.
假设您已二值化,因此背景为颜色 1,对象为颜色 0。设置 c = 2
,扫描零像素,并用颜色 c
对其进行填充。
现在增加 c
,扫描零,填充,起泡沫,冲洗,重复。
您最终会得到带有不同颜色的每个对象,因此您可以将其用作隔离遮罩。
不同的颜色在调试过程中非常有用,但如果您只想计数,当然三种颜色就足够了(甚至两种)。
最终位图在双色情况下统一为背景色。
使用 4 元素 Von Neumann neighborhood versus an 8-element neighborhood 会对最终结果产生很大影响。 通过 8 元素设置中的对角线连通性,绘制 "leak" 更容易。 进行边缘检测和加厚有助于减少不必要的颜色泄漏。