OpenCV Python删除小轮廓,保存子轮廓

时间:2020-06-19 16:03:35

标签: python opencv

我正在尝试删除除最大轮廓以外的所有轮廓,同时将子轮廓保留在最大轮廓内。实际上,我想从这里开始:Input Image到:Output Image尽管我也不知道该怎么做(我不是一个程序员,在下面的内容上有帮助)。我的代码没有保留子轮廓。 Output of Below.

import cv2 as cv
import numpy as np

img = cv.imread('small_contour.jpg')
image_contours = np.zeros((img.shape[1], img.shape[0], 1), np.uint8)

image_binary = np.zeros((img.shape[1], img.shape[0], 1), np.uint8)

for channel in range(img.shape[2]):
    ret, image_thresh = cv.threshold(img[:, :, channel], 127, 255, cv.THRESH_BINARY)    
    contours = cv.findContours(image_thresh, 1, 1)[0]   
    cv.drawContours(image_contours, contours, -1, (255,255,255), 3)

contours = cv.findContours(image_contours, cv.RETR_LIST,
                           cv.CHAIN_APPROX_SIMPLE)[0]

cv.drawContours(image_binary, [max(contours, key = cv.contourArea)],
                -1, (255, 255, 255), -1)

cv.imwrite('fill_contour.jpg', image_binary)
cv.imshow('Small Contour', image_binary)
cv.waitKey(0)

2 个答案:

答案 0 :(得分:1)

您在代码cv.drawContours(image_binary, [max(contours, key = cv.contourArea)], -1, (255, 255, 255), -1)中执行的操作是将(255, 255, 255)的像素image_binary的颜色设置为{{1}找到的较大轮廓的边界和内部像素}}。

创建cv.findContours时,您也在将宽度与高度交换,这是一个错误。

您不需要保留孩子:您应该使用image_binary,然后找到父亲的索引并查找所有轮廓,并由该父亲对嵌套轮廓(孩子的孩子)进行递归处理...)。请参见https://docs.opencv.org/4.1.0/d9/d8b/tutorial_py_contours_hierarchy.html,但这对您的目标没有用。


您可以将当前使用的结果用作原始图像的遮罩,但是代码需要一些修复,从名为cv.RETR_TREE的链接图像开始。 请注意,我正在使用VS0L9.jpg,只需更改为cv2

加载图像

cv

找到轮廓(我使用了RETR_TREE)

im = cv2.imread('VS0L9.jpg', cv2.IMREAD_GRAYSCALE)

找到更大的轮廓:

contours, hierarchy = cv2.findContours(im, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

初始化掩码(您对bigger = max(contours, key=lambda item: cv2.contourArea(item)) 进行的尝试)

image_binary

在蒙版图像上绘制较大轮廓的填充,将关注区域设置为(255,255,255):

the_mask = np.zeros_like(im)

这时,掩码看起来像代码的输出,但是具有适当的宽度和高度。 将遮罩与原始图像一起使用以仅显示感兴趣的区域:

cv2.drawContours(the_mask, [bigger], -1, (255, 255, 255), cv2.FILLED)

或者,或者:

res = cv2.bitwise_and(im, im, mask = the_mask)

现在res = im.copy() res[the_mask == 0] = 0 是理想的结果。

答案 1 :(得分:0)

您可以使用形态学重建,以侵蚀图像作为标记。

import cv2
img = cv2.imread('VS0L9.jpg', cv2.IMREAD_GRAYSCALE)
thresh = cv2.threshold(img, 40, 255, cv2.THRESH_BINARY)[1]
kernel=cv2.getStructuringElement(cv2.MORPH_RECT, (17,17))
kernel2 = cv2.getStructuringElement(cv2.MORPH_RECT, (3,3))
marker = cv2.erode(thresh,kernel,iterations = 5)
while True:
    tmp=marker.copy()
    marker=cv2.dilate(marker, kernel2)
    marker=cv2.min(thresh, marker)
    difference = cv2.subtract(marker, tmp)
    if cv2.countNonZero(difference) == 0:
        break

cv2.imwrite('out.png', marker)
cv2.imshow('result', marker )

enter image description here