Article Categories
- All Categories
-
Data Structure
-
Networking
-
RDBMS
-
Operating System
-
Java
-
MS Excel
-
iOS
-
HTML
-
CSS
-
Android
-
Python
-
C Programming
-
C++
-
C#
-
MongoDB
-
MySQL
-
Javascript
-
PHP
-
Economics & Finance
How to match image shapes in OpenCV Python?
We use cv2.matchShapes() function to match two image shapes in OpenCV. This function returns a metric showing the similarity between the image shapes using Hu-Moments to calculate the metric value. Lower the metric value, higher the similarity between the image shapes.
In the following examples, we will match the shapes from different images and also shapes from a single image.
Syntax
We use the following syntax to match two image shapes ?
ret = cv2.matchShapes(cnt1, cnt2, method, parameter)
Where,
cnt1 ? The contour points of the first image shape.
cnt2 ? The contour points of the second image shape.
method ? Comparison method (1, 2, or 3 for different Hu-moment variants).
parameter ? Method-specific parameter (typically 0.0).
Steps
You can use the following steps to match two image shapes ?
Step 1: Import the required library. In all the following Python examples, the required Python library is OpenCV. Make sure you have already installed it.
import cv2
Step 2: Read the input images as grayscale images using cv2.imread().
img1 = cv2.imread('star.png', 0)
img2 = cv2.imread('star1.png', 0)
Step 3: Apply thresholding on the grayscale images to create binary images.
ret, thresh1 = cv2.threshold(img1, 150, 255, 0) ret, thresh2 = cv2.threshold(img2, 150, 255, 0)
Step 4: Find the contours of the shapes in the binary images using cv2.findContours() function.
contours1, _ = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE) contours2, _ = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
Step 5: Select the particular contour from each image and apply the shape match function cv2.matchShapes() passing the selected contours.
cnt1 = contours1[0] cnt2 = contours2[0] ret12 = cv2.matchShapes(cnt1, cnt2, 1, 0.0)
Step 6: Print the result value, the image shape matching metric. The lower the value, the better matching it is.
print("Matching Image 1 with Image 2:", ret12)
Let's have a look at some examples for a better understanding.
Example 1: Matching Shapes from Different Images
In this program, we match two image shapes. Each image contains a single shape. We also match the shape with itself from each image ?
# import required libraries
import cv2
# Read two images as grayscale images
img1 = cv2.imread('star.png', 0)
img2 = cv2.imread('star1.png', 0)
# Apply thresholding on the images to convert to binary images
ret, thresh1 = cv2.threshold(img1, 127, 255, 0)
ret, thresh2 = cv2.threshold(img2, 127, 255, 0)
# find the contours in the binary image
contours1, hierarchy = cv2.findContours(thresh1, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("Number of Shapes detected in Image 1:", len(contours1))
cnt1 = contours1[0]
contours2, hierarchy = cv2.findContours(thresh2, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("Number of Shapes detected in Image 2:", len(contours2))
cnt2 = contours2[0]
# Compute the match scores
ret11 = cv2.matchShapes(cnt1, cnt1, 1, 0.0)
ret22 = cv2.matchShapes(cnt2, cnt2, 1, 0.0)
ret12 = cv2.matchShapes(cnt1, cnt2, 1, 0.0)
# print the matching scores
print("Matching Image 1 with itself:", ret11)
print("Matching Image 2 with itself:", ret22)
print("Matching Image 1 with Image 2:", ret12)
Consider the below images as the input images mentioned as 'star.png' and 'pentagon.png' in the above program.
Output
On execution, the above code will produce the following output ?
Number of Shapes detected in Image 1: 1 Number of Shapes detected in Image 2: 1 Matching Image 1 with itself: 0.0 Matching Image 2 with itself: 0.0 Matching Image 1 with Image 2: 0.6015851094057714
Example 2: Matching Multiple Shapes in Single Image
In this program, we match the shapes in a single image. We detect three shapes in the image and compare their similarities ?
import cv2
import numpy as np
img = cv2.imread('convexhull.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(gray, 100, 255, 0)
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
print("Number of Shapes detected:", len(contours))
# draw contour and shape number
for i, cnt in enumerate(contours):
M = cv2.moments(cnt)
x1, y1 = cnt[0, 0]
img1 = cv2.drawContours(img, [cnt], -1, (0, 255, 255), 3)
cv2.putText(img1, f'Shape:{i+1}', (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cnt1 = contours[0]
cnt2 = contours[1]
cnt3 = contours[2]
ret11 = cv2.matchShapes(cnt1, cnt1, 1, 0.0)
ret12 = cv2.matchShapes(cnt1, cnt2, 1, 0.0)
ret23 = cv2.matchShapes(cnt2, cnt3, 1, 0.0)
ret31 = cv2.matchShapes(cnt3, cnt1, 1, 0.0)
print("Matching Shape 1 with itself:", ret11)
print("Matching Shape 1 with Shape 2:", ret12)
print("Matching Shape 2 with Shape 3:", ret23)
print("Matching Shape 3 with Shape 1:", ret31)
cv2.imshow("Shapes", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
Output
On execution, the above code will produce the following output ?
Number of Shapes detected: 3 Matching Shape 1 with itself: 0.0 Matching Shape 1 with Shape 2: 0.15261042892128207 Matching Shape 2 with Shape 3: 0.9192709496955178 Matching Shape 3 with Shape 1: 0.7521097407160106
On the basis of the above result, we conclude that Shape 1 is more similar to Shape 2 than Shape 3, as indicated by the lower matching score of 0.152 compared to 0.752.
Key Points
A score of 0.0 indicates perfect match (identical shapes)
Lower scores indicate higher similarity between shapes
The function uses Hu-Moments which are invariant to translation, rotation, and scaling
Method parameter 1, 2, or 3 corresponds to different Hu-moment comparison techniques
Conclusion
The cv2.matchShapes() function provides an effective way to compare shape similarities using Hu-Moments. Lower metric values indicate higher similarity, with 0.0 representing identical shapes.
