OpenCV shape matching between two similar shapes

前端 未结 3 1310
伪装坚强ぢ
伪装坚强ぢ 2021-02-06 12:05

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

3条回答
  •  长情又很酷
    2021-02-06 13:05

    This answer is based on ZdaR's answer here https://stackoverflow.com/a/55530040/1787145. I have tried some variations in hope of using a single discerning criterion (cv2.matchShapes()) by incorporating more in the pre-processing.

    1. Compare images instead of contours

    I like the idea of normalization (crop and resize). But after shrinking an image, its originally closed contour might be broken into multiple disconnected parts, due to the low resolution of pixels. The result of cv2.matchShapes() is unreliable. By comparing whole resized images, I get following results. It says the circle is the most similar. Not good!

    2. Fill the shape

    By filling the shape, we take area into consideration. The result looks better, but DVI still beats HDMI for having a more similar height or Height/Width ratio. We want to ignore that.

    3. Resize every image to the same size

    By resizing all to the same size, we eliminate some ratio in the dimensions. (300, 300) works well here.

    4. Code

    def normalize_filled(img):
        img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        im, cnt, _ = cv2.findContours(img.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
        # fill shape
        cv2.fillPoly(img, pts=cnt, color=(255,255,255))
        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]]
        # resize all to same size
        img_resized = cv2.resize(img_cropped_bounding_rect, (300, 300))
        return img_resized
    
    imgs = [imgQuery, imgHDMI, imgDVI, img5PinDin, imgDB25]
    imgs = [normalize_filled(i) for i in imgs]
    
    for i in range(1, 6):
        plt.subplot(2, 3, i), plt.imshow(imgs[i - 1], cmap='gray')
        print(cv2.matchShapes(imgs[0], imgs[i - 1], 1, 0.0))
    

提交回复
热议问题