简体   繁体   中英

Is it possible to use OpenCV contour in python in a way that corners are not cut off?

I am using the OpenCV contour function in python. For example on an image like this:

在此处输入图片说明

contours, _ = cv2.findContours(img_expanded_padded, cv2.RETR_TREE, cv2.CHAIN_APPROX_NONE)

在此处输入图片说明 It works well except that it cuts off the corners on the inside of the contour as seen above. Are there any options that would leave this corner in?

Travelling along the contours and filling them in manually will be too computationally expensive. The above is only an example. This will be performed many times on images 5400x5400 or more...

I can find the edges with the code below, and have filled corners as a result but then I need to extract these as contours again.

# FIND ALL HORIZONTAL AND VERTICAL EDGES AND COMBINE THEM
edges_expanded_x = np.absolute(cv2.Sobel(img_expanded_padded,cv2.CV_64F, 1, 0, ksize=3))
edges_expanded_y = np.absolute(cv2.Sobel(img_expanded_padded,cv2.CV_64F, 0, 1, ksize=3))
edges_expanded = np.logical_or(edges_expanded_x, edges_expanded_y)

# GET RID OF DOUBLE EDGE THAT RESULTS FROM SOBEL FILTER
edges_expanded = np.multiply(img_expanded_padded,edges_expanded)

Are there any OpenCV settings or functions I can use to accomplish this?

EDIT: I should clarify, that my goal is to have a single pixel continous contour. I need the contours and not an array of the entire image including the contours.

EDIT: The above images are zoomed into my test image. The actual pixels are as shown by the red grids in the images below.

在此处输入图片说明

在此处输入图片说明

There is no need to use cv2.Sobel you can simply draw contours with cv2.drawContours on a black background. The black background can be drawn with the help of np.zeros.

img = cv2.imread('contouring.png',0)
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
bgr = np.zeros((img.shape[0], img.shape[1]), dtype= 'uint8')
cv2.drawContours(bgr, contours, -1, (255,255,255), 1)

薄底

If you want the contour lines to be thick then you use cv2.dilate for that. Then to prevent the cutting of corners cv2.bitwise_and can be used along with cv2.bitwise_not as shown below

bgr = cv2.dilate(bgr, np.ones((31, 31), np.uint8), iterations=1)
bgr = cv2.bitwise_and(bgr, cv2.bitwise_not(img))

This gives contours which are 15 pixels thick. 厚边

EDIT - The first image of thin contours is still cutting corners. To obtain single pixel contours which do not corners we can use a kernel size of 3*3.

img = cv2.imread('contouring.png',0)
contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
bgr = np.zeros((img.shape[0], img.shape[1]), dtype= 'uint8')
cv2.drawContours(bgr, contours, -1, (255,255,255), 1)
bgr = cv2.dilate(bgr, np.ones((3, 3), np.uint8), iterations=1)
bgr = cv2.bitwise_and(bgr, cv2.bitwise_not(img))

This gives us结果

I have checked it by using cv2.bitwise_and between bgr and img and I obtain a black image indicating that no white pixels are cutting corners.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM