I\'m trying to match a slightly irregular shape to a database of shapes. For example, here the contour I\'m trying to match:
For more information, this is an ou
There are multiple steps which can be performed to get better results. And there is no need of a CNN or some complex feature matching, lets try to solve this using very basic approached.
This can be done by closely cropping the input contour and then resize all the images either to same height or width. I will chose width here, let's say 300px. Let's define a utility method for this:
def normalize_contour(img):
im, cnt, _ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
bounding_rect = cv2.boundingRect(cnt[0])
img_cropped_bounding_rect = img[bounding_rect[1]:bounding_rect[1] + bounding_rect[3],
bounding_rect[0]:bounding_rect[0] + bounding_rect[2]]
new_height = int((1.0 * img.shape[0])/img.shape[1] * 300.0)
img_resized = cv2.resize(img_cropped_bounding_rect, (300, new_height))
return img_resized
This code snippet would return a nicely cropped contour with a fixed width of 300. Apply this method to all the database images and input query image as well.
Since we have normalized the input image to 300 px we can reject all the candidates whose height is not close to the normalized image height. This will rule out 5PinDIN.
Now you can try sorting the results with max overlap, you can cv2.contourArea()
to get the contour area and sort all the remaining candidates to get the closest possible match.