Geometric shape recognition and measurement in OpenCV
I often see people who have learned OpenCV not long ago asking how to recognize some simple geometric shapes and their colors. In fact, with OpenCV's contour discovery and geometric analysis related functions, it takes less than 100 lines of code to implement these simple geometric shape recognition and object measurement related operations very well. This article will show you how to implement the following functions through OpenCV contour discovery and geometric analysis related functions.
Before we get to the specific code implementation and program demonstration, let's get some concepts straight.
What is a contour? Simply put, a contour is a series of points connected to form a shape, they have the same color, contour discovery is a very useful tool for object analysis, object detection, etc. When using contour discovery related functions in OpenCV, the input image is required to be a binary image, so that it is easy to contour extraction, edge extraction and other operations. The functions and parameters for profile discovery are explained as follows.
findContours(image, mode, method, contours=None, hierarchy=None, offset=None) - image input/output binary image - mode returns the structure of the profile, which can be List, Tree, External - method The way contour points are encoded is basically based on the chain encoding - contours The set of contours returned - hieracrchy returns the contour hierarchy - Whether the offset point is displaced
polygonalloom, is achieved by infinitely approximating the profile shape, Removal of non-critical points、 Key points for getting the profile, A method of constantly approximating the true shape of a silhouette,OpenCV in polygonal The functions and parameters of the approximation are explained as follows:
approxPolyDP(curve, epsilon, closed, approxCurve=None) - curve indicates the set of input contour points - epsilon denotes the approximation curvature, smaller means more similar approximation - close Whether to close
The image geometric distance is a geometric feature of the image, and the higher-order geometric distance has feature invariance after centering, which can produce Hu distance output for operations such as shape matching, Here we get the center position of the specified contour by calculating the first-order geometric distance, and the function and parameters for calculating the geometric distance are explained as follows.
moments(array, binaryImage=None) - array indicates the specified input profile - binaryImage defaults to None
Based on contour discovery and polygon approximation, geometric distance for geometric shape recognition and object measurement, two other related APIs are used to calculate the perimeter and area of the contour respectively. The exact usage is reflected in the code. The entire code is implemented in the following steps: 1. Image binarization
# binarized image print("start to detect lines... ") gray = cv.cvtColor(frame, cv.COLOR_BGR2GRAY) ret, binary = cv.threshold(gray, 0, 255, cv.THRESH_BINARY_INV | cv.THRESH_OTSU) cv.imshow("input image", frame)
2.Contour Discovery
out_binary, contours, hierarchy = cv.findContours(binary, cv.RETR_EXTERNAL, cv.CHAIN_APPROX_SIMPLE) for cnt in range(len(contours)): # Extracting and drawing contours cv.drawContours(result, contours, cnt, (0, 255, 0), 2)
3.geometric shape recognition
# silhouette approaching epsilon = 0.01 * cv.arcLength(contours[cnt], True) approx = cv.approxPolyDP(contours[cnt], epsilon, True) # Analyze the geometry corners = len(approx) shape_type = "" if corners == 3: count = self.shapes['triangle'] count = count+1 self.shapes['triangle'] = count shape_type = " triangular" if corners == 4: count = self.shapes['rectangle'] count = count + 1 self.shapes['rectangle'] = count shape_type = " rectangles" if corners >= 10: count = self.shapes['circles'] count = count + 1 self.shapes['circles'] = count shape_type = " circle" if 4 < corners < 10: count = self.shapes['polygons'] count = count + 1 self.shapes['polygons'] = count shape_type = " polygonal"
4.Measure perimeter, area, calculate center
# Solve for center location mm = cv.moments(contours[cnt]) cx = int(mm['m10'] / mm['m00']) cy = int(mm['m01'] / mm['m00']) cv.circle(result, (cx, cy), 3, (0, 0, 255), -1) # Calculate area and perimeter p = cv.arcLength(contours[cnt], True) area = cv.contourArea(contours[cnt])
5.Color Extraction
# Color Analysis color = frame[cy][cx] color_str = "(" + str(color[0]) + ", " + str(color[1]) + ", " + str(color[2]) + ")"
The run shows the original image as follows.