Get boundary from canny edges and remove the background of an image

匆匆过客 提交于 2021-01-24 02:26:48

问题


I'm trying to remove the background of an image that im trying to train a neural network with. I've had little luck using the method described here (How do I remove the background from this kind of image?), but I have been able to use the Canny Edge Detector to get a semi-good "boundary" of the object in my image. Heres my code I'm running

import cv2 as cv, sys, numpy as np, PIL.Image, matplotlib.pylab as plt

# read command-line arguments
filename = '/Users/colew/Desktop/Good_Cups_Frames/frame_IMG_2057.MOV_0.jpg'

img = cv.imread(filename,0)
edges = cv.Canny(img,25,200)
plt.subplot(121),plt.imshow(img,cmap = 'gray')
plt.title('Original Image'), plt.xticks([]), plt.yticks([])
plt.subplot(122),plt.imshow(edges,cmap = 'gray')
plt.title('Edge Image'), plt.xticks([]), plt.yticks([])
plt.savefig("pic")
plt.show()

and the resulting image(s) we get are

So what I'm looking for exactly is a way for me to get the boundaries of the canny edges and then from there, crop the original image around these boundaries. Thanks!


回答1:


If I understand correctly, you want to remove the background and extract the object. Instead of using Canny, here's an alternative approach. Since you didn't provide an original image, I screenshotted your image to use as input. In general, there are several ways to obtain a binary image for boundary extraction. They include regular thresholding, Otsu's thresholding, Adaptive thresholding, and Canny edge detection. In this case, Otsu's is probably the best since there is background noise


First we convert the image to grayscale then perform Otsu's threshold to obtain a binary image

There are unwanted sections so to remove them, we perform a morph open to separate the joints

Now that the joints are separated, we find contours and filter using contour area. We extract the largest contour which represents the desired object then draw this contour onto a mask

We're almost there but there are imperfections so we morph close to fill the holes

Next we bitwise-and with the original image

Finally to get the desired result, we color in all black pixels on the mask to white

From here you could use Numpy slicing to extract the ROI but I'm not completely sure what you were trying to do. I'll leave that up to you

import cv2
import numpy as np

image = cv2.imread("1.png")
original = image.copy()
mask = np.zeros(image.shape, dtype=np.uint8)
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5,5))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

cnts = cv2.findContours(opening, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
cnts = sorted(cnts, key=cv2.contourArea, reverse=True)
for c in cnts:
    cv2.drawContours(mask, [c], -1, (255,255,255), -1)
    break

close = cv2.morphologyEx(mask, cv2.MORPH_CLOSE, kernel, iterations=4)
close = cv2.cvtColor(close, cv2.COLOR_BGR2GRAY)
result = cv2.bitwise_and(original, original, mask=close)
result[close==0] = (255,255,255)

cv2.imshow('result', result)
cv2.waitKey()


来源:https://stackoverflow.com/questions/58613825/get-boundary-from-canny-edges-and-remove-the-background-of-an-image

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