如何在opencv中根据深度颜色分割连通区域
how to segment the connected area based on depth color in opencv
我有一张像这样的图片,我需要将图片分割成8块。
这个阈值法我试过了
img_gray = cv2.imread(input_file,cv2.IMREAD_GRAYSCALE)
ret,thresh = cv2.threshold(img_gray,254,255,cv2.THRESH_BINARY) =
kernel = np.array(cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1)))
img_open = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
cv2.imshow('abc',img_open)
ret1,thresh1 = cv2.threshold(img_open,254,255,cv2.THRESH_BINARY_INV) #
contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_CCOMP ,cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
if len(contours[i]) > 20:
x, y, w, h = cv2.boundingRect(contours[i])
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
print (x, y),(x+w, y+h)
阈值处理后
最后的结果是一些块连在一起形成了一个大段,这不是我所希望的。
任何其他解决方法
朴素的方法(但它有效)
第一步:读取灰度图像后,阈值得到底车。
ret1, car_thresh1 = cv2.threshold(cars, 191, 254, 0)
这给了我这个。
第 2 步:从主图像中减去此图像
car_thresh2 = car_thresh1 - cars
这给了我这个。
第 3 步:阈值减影图像
ret3, cars_thresh3 = cv2.threshold(car_thresh2, 58, 255, 0)
这给了我这个
然后我简单地做了你在 carsTop 和 carsBottom 中提取和绘制轮廓的操作,这就是结果。
我会尝试给你一个基于深度梯度分离汽车的算法草图。唉,单纯看大深度梯度的轮廓,车子并没有完全分开,所以需要一些"refinement"的边界轮廓。一旦轮廓完成,一个简单的连接组件聚类就足以分离汽车。
这是我的代码(在 Matlab 中,但我很确定找到 opencv 等效函数并不太复杂):
img = imread('http://i.stack.imgur.com/8lJw8.png'); % read the image
depth = double(img(:,:,1));
depth(depth==255)=-100; % make the background VERY distinct
[dy dx] = gradient(depth); % compute depth gradients
bmsk = sqrt(dx.^2+dy.^2) > 5; % consider only significant gradient
% using morphological operations to "complete" the contours around the cars
bmsk = bwmorph( bwmorph(bmsk, 'dilate', ones(7)), 'skel');
% once the contours are complete, use connected components
cars = bwlabel(~bmsk,4); % segmentation mask
st = regionprops(cars, 'Area', 'BoundingBox');
% display the results
figure;
imshow(img);
hold all;
for ii=2:numel(st), % ignore the first segment - it's the background
if st(ii).Area>200, % ignore small regions as "noise"
rectangle('Position',st(ii).BoundingBox, 'LineWidth', 3, 'EdgeColor', 'g');
end;
end;
输出为
和
不完美,但足够接近。
延伸阅读:
bwmorph
:进行词法运算。
bwlabel
:输出连通分量的分割掩码(标记)。
regionprops
:计算图像区域的统计数据(例如面积和边界框)。
想到这一点,深度有很好的梯度,你可以对深度梯度进行阈值处理,得到很好的连通分量。
我有一张像
这个阈值法我试过了
img_gray = cv2.imread(input_file,cv2.IMREAD_GRAYSCALE)
ret,thresh = cv2.threshold(img_gray,254,255,cv2.THRESH_BINARY) =
kernel = np.array(cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3), (-1, -1)))
img_open = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel)
cv2.imshow('abc',img_open)
ret1,thresh1 = cv2.threshold(img_open,254,255,cv2.THRESH_BINARY_INV) #
contours, hierarchy = cv2.findContours(thresh1, cv2.RETR_CCOMP ,cv2.CHAIN_APPROX_NONE)
for i in range(len(contours)):
if len(contours[i]) > 20:
x, y, w, h = cv2.boundingRect(contours[i])
cv2.rectangle(img, (x, y), (x+w, y+h), (0, 255, 0), 2)
print (x, y),(x+w, y+h)
阈值处理后
最后的结果是一些块连在一起形成了一个大段,这不是我所希望的。
朴素的方法(但它有效)
第一步:读取灰度图像后,阈值得到底车。
ret1, car_thresh1 = cv2.threshold(cars, 191, 254, 0)
这给了我这个。
第 2 步:从主图像中减去此图像
car_thresh2 = car_thresh1 - cars
这给了我这个。
第 3 步:阈值减影图像
ret3, cars_thresh3 = cv2.threshold(car_thresh2, 58, 255, 0)
这给了我这个
然后我简单地做了你在 carsTop 和 carsBottom 中提取和绘制轮廓的操作,这就是结果。
我会尝试给你一个基于深度梯度分离汽车的算法草图。唉,单纯看大深度梯度的轮廓,车子并没有完全分开,所以需要一些"refinement"的边界轮廓。一旦轮廓完成,一个简单的连接组件聚类就足以分离汽车。
这是我的代码(在 Matlab 中,但我很确定找到 opencv 等效函数并不太复杂):
img = imread('http://i.stack.imgur.com/8lJw8.png'); % read the image
depth = double(img(:,:,1));
depth(depth==255)=-100; % make the background VERY distinct
[dy dx] = gradient(depth); % compute depth gradients
bmsk = sqrt(dx.^2+dy.^2) > 5; % consider only significant gradient
% using morphological operations to "complete" the contours around the cars
bmsk = bwmorph( bwmorph(bmsk, 'dilate', ones(7)), 'skel');
% once the contours are complete, use connected components
cars = bwlabel(~bmsk,4); % segmentation mask
st = regionprops(cars, 'Area', 'BoundingBox');
% display the results
figure;
imshow(img);
hold all;
for ii=2:numel(st), % ignore the first segment - it's the background
if st(ii).Area>200, % ignore small regions as "noise"
rectangle('Position',st(ii).BoundingBox, 'LineWidth', 3, 'EdgeColor', 'g');
end;
end;
输出为
和
不完美,但足够接近。
延伸阅读:
bwmorph
:进行词法运算。bwlabel
:输出连通分量的分割掩码(标记)。regionprops
:计算图像区域的统计数据(例如面积和边界框)。
想到这一点,深度有很好的梯度,你可以对深度梯度进行阈值处理,得到很好的连通分量。