如何使用 Python/Opencv 分割二进制图像中的附近元素

Posted

技术标签:

【中文标题】如何使用 Python/Opencv 分割二进制图像中的附近元素【英文标题】:How to segment nearby elements in a binary image using Python/Opencv 【发布时间】:2017-08-03 01:08:49 【问题描述】:

我有这个二进制图像,其中每个“曲线”代表一堆这些物体中的一顶帽子。它是通过对堆叠的草帽原始图像的一个区域进行阈值处理获得的。

如您所见,这些曲线的形状内部有许多间隙,这很难使用像 cv.connectedcomponentes 这样的技术来获取图像中对象的数量,这是我的目标。

我认为如果有一些技术可以填补这些空白和/或主要是原始二进制图像的较小部分中的孔,就像我在下面展示的那样,也许是 连接附近的元素检测和填充轮廓,可以将每条曲线分割为一个单独的元素

【问题讨论】:

【参考方案1】:

不是最优雅的方式,但应该足够简单。 考虑w 的垂直切片(与您在问题中发布的切片相同)。如果你沿着切片的行对白色像素求和,你应该得到六个漂亮的“峰值”,对应于帽子的六个边缘:

但是,由于轮辋是圆形的,因此对于这种估计,某些垂直切片会比其他切片更好。 因此,我建议查看 所有 个宽度为 w 的切片并计算每个切片的峰值。 这是一个执行此操作的 Matlab 代码

img = imread('http://i.stack.imgur.com/69FfJ.jpg');  % read the image
bw = img(:,:,1)>128;  % convert to binary 

w = 75;  % width of slice
all_slices = imfilter(single(bw), ones(1,w)/w, 'symmetric')>.5;  % compute horizontal sum of all slices using filter
% a peak is a slice with more than 50% "white" pixels
peaks = diff( all_slices, 1, 1 ) > 0;  % detect the peaks using vertical diff
count_per_slice = sum( peaks, 1 );  % how many peaks each slice think it sees

count_per_slice的分布:

您会看到,尽管许多切片预测了错误的帽子数量(4 到 9 之间),但大多数人投票支持正确的数字 6:

num_hats = mode(count_per_slice);  % take the mode of the distribution.

执行相同操作的 python 代码(假设 bwshape (h,w) 和 dtype bool 的 numpy 数组):

from scipy import signal, stats
import numpy as np
w = 75;
all_slices = signal.convolve2d( bw.astype('f4'), np.ones((1,w),dtype='f4')/float(w), mode='same', boundary='symmetric')>0.5
peaks = np.diff( all_slices, n=1, axis=0 ) > 0
count_per_slice = peaks.sum( axis=0 )
num_hats = stats.mode( count_per_slice )

【讨论】:

为了提高稳定性,你可以先用一个小内核卷积(scipy.signal.convolve2d)图像(例如np.ones((n,n)),这将缩小小间隙。这将首先给你一个填充整数的数组,但您可以将其转换回具有正确阈值的布尔值 @JürgMerlinSpaak 实际上,使用过滤器形状和值可能会增加该方法的稳健性。我在这里只展示了一个最小的解决方案,用作进一步研究和改进的基准 谢谢你们的建议,伙计们!我使用的方法和你做的类似,Shai。我将二进制图像分割成许多部分,比如 250 到 300,然后在每个部分中进行一些增强(侵蚀、膨胀和打开),并计算所有部分中的白色部分。我在这种方法中的努力是消除这些白色元素内部的一些剩余孔,以提高计算的准确性(在一小部分中,一个孔通过分离白色像素将 1 个帽子变成 2 个),因为事实上,此图像只是原始图像的一个区域,实际上包含 85 顶帽子。

以上是关于如何使用 Python/Opencv 分割二进制图像中的附近元素的主要内容,如果未能解决你的问题,请参考以下文章

Python + OpenCV:OCR 图像分割

使用Python,OpenCV,本地二进制模式(LBP)进行人脸识别

python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)

python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)

python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)

python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)