I have a function that erodes certain contours more or less depending on their area size. However, once they are cropped they lose the proper coordinate data that corresponds to the original image.
How can I redraw my eroded_contours
to the original image while maintaining their original position? Or is there a better approach to using custom erosion based on contour area size?
edged = cv2.Canny(original_image.copy(), 50, 200)
contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
def show_each_contour(original_image):
for i,c in enumerate(contours):
area = cv2.contourArea(c)
if area > 0:
rect = cv2.boundingRect(c)
x,y,w,h = rect
start_row, start_col = int(x), int(y)
end_row, end_col = int(x+x+w), int(y+y+h)
cv2.rectangle(original_image, (x,y), (x+w,y+h), (0,0,255), 2)
cropped = original_image[y:y+h, x:x+w]
if area < 2000:
kernel = np.ones((5,5), np.uint8)
numberOfIterations = area / 200
else:
kernel = np.ones((5,5), np.uint8)
numberOfIterations = 7
eroded_contours = cv2.erode(cropped.copy(), kernel, iterations = int(numberOfIterations))
#This won't work correctly because the coordinates are different now
#cv2.drawContours(original_image, eroded_contours , -1, (0,255,255), 3)
If I understood correctly what you are asking, you were pretty close to your goal.
Here is what I came up with (using Python 3.6 & OpenCV 3.2) :
edged = cv2.Canny(input_img.copy(), 50, 200)
_, contours, hierarchy = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # note that this function returns 3 values
def show_each_contour(original_image):
margin = 2 # you can set the margin to 0 to better understand its effect
for i,c in enumerate(contours):
area = cv2.contourArea(c)
if area > 0:
rect = cv2.boundingRect(c)
x,y,w,h = rect
cv2.rectangle(original_image, (x-margin,y-margin), (x+w+margin,y+h+margin), (0,0,255), 2)
cropped = original_image[y-margin:y+h+margin, x-margin:x+w+margin]
if area < 2000:
kernel = np.ones((5,5), np.uint8)
numberOfIterations = area / 200
else:
kernel = np.ones((5,5), np.uint8)
numberOfIterations = 7
eroded_shape = cv2.erode(cropped.copy(), kernel, iterations = int(numberOfIterations))
original_image[y-margin:y+h+margin, x-margin:x+w+margin] = eroded_shape # we copy the eroded_shape back into the original_image
I didn't change much of your code besides the last line where I copy the eroded shape into the right location of the original image.
Input image on the left side, and the output on the right side.
Hope this helps and please tell me if this is not what you were looking for.