how to segment the connected area based on depth color in opencv

拜拜、爱过 提交于 2021-02-18 06:33:38

问题


I have a picture like , which i need to segment the picture into 8 blocks.

I have tried this threshold method

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)

after the thresholding

the end result is some blocks connected together are formed into a large segment, which is not what I hoped. Any other ways to get it around


回答1:


I'll try and give you a sketch of an algorithm that separates the cars based on depth gradients. Alas, simply looking at the contour of large depth gradients, the cars are not perfectly separated, therefore, some "refinement" of the boundary contour is required. Once the contours are complete, a simple connected component clustering is sufficient to separate the cars.

Here's my code (in Matlab, but I'm quite certain it's not too complex to find opencv equivalent functions):

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;

The output is

And

Not perfect, but brings you close enough.

Further reading:

  • bwmorph: to perform morphological operations.
  • bwlabel: to output a segmentation mask (labeling) of the connected components.
  • regionprops: compute statistics (e.g., area and bounding box) for image regions.

Coming to think of it, depth has such nice gradients, you can threshold the depth gradient and get nice connected components.




回答2:


Naive Approach (But it works)

Step 1: After reading the image in gray scale, threshold to get bottom cars.

ret1, car_thresh1 = cv2.threshold(cars, 191, 254, 0)

which gave me this.

Step 2: Subtract this image from the main image

car_thresh2 = car_thresh1 - cars

which gave me this.

Step 3: Threshold the subtracted image

ret3, cars_thresh3 = cv2.threshold(car_thresh2, 58, 255, 0)

which gave me this

Then I simply did what you did for extracting and drawing contours in the carsTop and carsBottom and this is the result.



来源:https://stackoverflow.com/questions/45247717/how-to-segment-the-connected-area-based-on-depth-color-in-opencv

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!