如何使用 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 代码(假设 bw
是 shape
(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,本地二进制模式(LBP)进行人脸识别
python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)
python+opencv 实现文字分割(横板-小票文字分割/竖版-古文文字分割)