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

时间:2017-08-03 01:08:49

标签: python opencv image-processing image-segmentation

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

Binary Image

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

我认为如果有一些技术来填补这些间隙和/或主要是空洞,在原始二进制图像的较小部分,就像我正在展示的那些,可能是 连接附近的元素 检测和填充轮廓 ,可以将每条曲线细分为单个元素

Smaller Region 1

Smaller Region 2

1 个答案:

答案 0 :(得分:2)

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

enter image description here

然而,由于轮辋是圆形的,因此对于这种估计,一些垂直切片会比其他切片更好 因此,我建议查看宽度为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

的分布情况

enter image description here

你看,虽然许多切片预测了错误的帽子数量(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 )