问题
I am using openCV in python to detect cracks in concrete. I am able to use canny edge detection to detect cracks. Next, I need to fill the edges. I used floodfill operation of openCV but some of the gaps are filled whereas some are not filled. The image on the left is the input image whereas that on the right is the floodfilled image. I am guessing this is because my edges have breaks at points. How do i solve this ? My code for floodfilling:
im_th1 = imginput
im_floodfill = im_th1.copy()
# Mask used to flood filling.
# Notice the size needs to be 2 pixels than the image.
h, w = im_th1.shape[:2]
mask = np.zeros((h + 2, w + 2), np.uint8)
# Floodfill from point (0, 0)
cv2.floodFill(im_floodfill, mask, (5, 5), 255);
# Invert floodfilled image
im_floodfill_inv = cv2.bitwise_not(im_floodfill)
# Combine the two images to get the foreground.
im_out = im_th1 | im_floodfill_inv
cv2.imshow("Foreground", im_out)
cv2.waitKey(0)
回答1:
I see this so often here on SO, everybody wants to use edge detection, and then fill in the area in between the edges.
Unless you use a method for edge detection that purposefully creates a closed contour, detected edges will likely not form a closed contour. And you cannot flood-fill a region unless you have a closed contour.
In most of these cases, some filtering and a simple threshold suffice. For example:
import PyDIP as dip
import matplotlib.pyplot as pp
img = dip.Image(pp.imread('oJAo7.jpg')).TensorElement(1) # From OP's other question
img = img[4:698,6:]
lines = dip.Tophat(img, 10, polarity='black')
dip.SetBorder(lines, [0], [2])
lines = dip.PathOpening(lines, length=100, polarity='opening', mode={'robust'})
lines = dip.Threshold(lines, method='otsu')[0]
This result is obtained after a simple top-hat filter, which keeps only thin things, followed by a path opening, which keeps only long things. This combination removes large-scale shading, as well as the small bumps and things. After the filtering, a simple Otsu threshold yields a binary image that marks all pixels in the crack.
Notes:
- The input image is the one OP posted in another question, and is the input to the images posted in this question.
- I'm using PyDIP, which you can get on GitHub and need to compile yourself. Hopefully soon we'll have a binary distribution. I'm an author.
回答2:
I found the solution to what i was looking for. Posting it here as it might come of use to others. After some research on the internet, it was just 2 lines of codes as suggested in this : How to complete/close a contour in python opencv?
The code that worked for me is :
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (9, 9))
dilated = cv2.dilate(image, kernel)
eroded=cv2.erode(dilated,kernel)
The result is in the image attached that shows before and after results.
来源:https://stackoverflow.com/questions/53358598/filling-edges-using-flood-fill-not-working-properly