OpenCV implements object size measurement

One, project analysis

The idea of object size measurement is to find an object with a certain size as a reference and calculate the size of the unknown object based on the known ones.

As shown in the picture below, the size of the green board is 220*300 (unit: mm), and the length of the white paper is calculated through the program.

Mainly through image processing technology, the size measurement of objects in a picture is achieved. The specific requirements are as follows:

  1. Read in a picture that contains the object that needs to be measured

  2. Perform edge detection on the image to find all contours

  3. Select the contour with the largest area among all contours, which is the object to be measured.

  4. Perform a perspective transformation on the object to turn it into a rectangle

  5. In a rectangle, determine the height and width of the object through the intersection points of the line segments.

  6. Convert height and width to actual dimensions and label them on the image

  7. Display the results on the screen.

Second, implementation process

  1. Import the necessary libraries: cv2 and numpy.

import cv2
import numpy as np

2. Define some parameters: scaling ratio, width and height of the output image.

scale=2
wP = 220 * scale
hP = 300 * scale

3. Define a function getContours to obtain the contours in the image. This function first converts the image to grayscale, then performs Gaussian blur, then performs Canny edge detection, then performs dilation and erosion operations, and finally uses the findContours function to find all outer contours. Perform contour filtering based on the conditions of area and number of inflection points, and return the filtered contour list.

def getContours(img, cThr=[100, 100], showCanny=False, minArea=1000, filter=0, draw=False):
    imgGray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    imgBlur = cv2.GaussianBlur(imgGray, (5, 5), 1)
    imgCanny = cv2.Canny(imgBlur, cThr[0], cThr[1])
    kernel = np.ones((5, 5))
    imgDial = cv2.dilate(imgCanny, kernel, iterations=3)
    imgThre = cv2.erode(imgDial, kernel, iterations=2)
    if showCanny: cv2.imshow('Canny', imgThre)

    # Find all outer contours
    _, contours, _ = cv2.findContours(imgThre, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    finalCountours = []
    # Traverse the found contours
    for i in contours:
        area = cv2.contourArea(i) # Area of the contour
        if area > minArea: # If it is greater than the set minimum outline value, go down
            peri = cv2.arcLength(i, True) # The length of the closed contour
            approx = cv2.approxPolyDP(i, 0.02 * peri, True) # The inflection point of the closed contour
            bbox = cv2.boundingRect(approx) # Find the bounding box
            if filter > 0: # Do you need to filter contours based on the number of inflection points?
                if len(approx) == filter: # Number of inflection points, area, inflection point position, bounding box, outline
                    finalCountours.append([len(approx), area, approx, bbox, i])
            else:
                finalCountours.append([len(approx), area, approx, bbox, i])
    finalCountours = sorted(finalCountours, key=lambda x: x[1], reverse=True) # Sort from large to small according to the outline size
    if draw: # Whether to draw the outline
        for con in finalCountours:
            cv2.drawContours(img, con[4], -1, (0, 0, 255), 3)
    return img, finalCountours

4. A function reorder is defined to reorder the order of four points. Sort according to the maximum and minimum values of the sum and difference of the four points, and return the reordered points.

def reorder(myPoints):
    myPointsNew = np.zeros_like(myPoints)
    myPoints = myPoints.reshape((4, 2))
    add = myPoints.sum(1)
    myPointsNew[0] = myPoints[np.argmin(add)]
    myPointsNew[3] = myPoints[np.argmax(add)]
    diff = np.diff(myPoints, axis=1)
    myPointsNew[1] = myPoints[np.argmin(diff)]
    myPointsNew[2] = myPoints[np.argmax(diff)]

    return myPointsNew

5. Define a function warpImg for perspective transformation of images. Based on the four input points and the width and height of the output image, use the getPerspectiveTransform function to calculate the perspective transformation matrix, then use the warpPerspective function to perform perspective transformation, and transform the transformed image Make a cut.

def warpImg(img, points, w, h, pad=20):
    # print(points)
    points = reorder(points)
    pts1 = np.float32(points)
    pts2 = np.float32([[0, 0], [w, 0], [0, h], [w, h]])
    matrix = cv2.getPerspectiveTransform(pts1, pts2)
    imgWrap = cv2.warpPerspective(img, matrix, (w, h))
    imgWrap = imgWrap[pad:imgWrap.shape[0] - pad, pad:imgWrap.shape[1] - pad]

    return imgWrap

6. Define a function findDis for calculating the distance between two points.

def findDis(pts1, pts2):
    return ((pts2[0] - pts1[0]) ** 2 + (pts2[1] - pts1[1]) ** 2) ** 0.5

7. Read the input image and scale it to the specified size.

path = 'E:\All_in\opencv\chicun.png'
img = cv2.imread(path)
img = cv2.resize(img, (0, 0), None, 0.18, 0.18)

8. Use the getContours function to obtain the contours in the image, set the minimum contour area to 8000, the number of inflection points to 4, and return the filtered contour list.

img, conts = getContours(img, minArea=8000, filter=4)

9. Determine whether there is a contour. If it exists, find the inflection point position of the largest contour, use the warpImg function to perform perspective transformation on the image, and return the transformed image.

if len(conts) != 0:
    biggest = conts[0][2] #The inflection point position of the largest contour
    # print(biggest)
    imgWrap = warpImg(img, biggest, wP, hP)

10. Use the getContours function again to obtain the contours of the transformed image, set the minimum contour area to 2000, the number of inflection points to 4, and return the filtered contour list.

 imgContours2, conts2 = getContours(imgWrap, minArea=2000, filter=4, cThr=[50, 50])

11. Traverse the filtered contour list, draw polygons and arrows for each contour, calculate the length in both directions, and then mark the length information on the image.

 if len(conts) != 0:
        for obj in conts2:
            cv2.polylines(imgContours2, [obj[2]], True, (0, 255, 0), 2)
            nPoints = reorder(obj[2])
            nW = round((findDis(nPoints[0][0] // scale, nPoints[1][0] // scale) / 10), 1)
            nH = round((findDis(nPoints[0][0] // scale, nPoints[2][0] // scale) / 10), 1)
            #Create arrow
            cv2.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[1][0][0], nPoints[1][0][ 1]),
                            (255, 0, 255), 3, 8, 0, 0.05)
            cv2.arrowedLine(imgContours2, (nPoints[0][0][0], nPoints[0][0][1]), (nPoints[2][0][0], nPoints[2][0][ 1]),
                            (255, 0, 255), 3, 8, 0, 0.05)
            x, y, w, h = obj[3]
            cv2.putText(imgContours2, '{}cm'.format(nW), (x + 30, y - 10), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,
                        (255, 0, 255), 2)
            cv2.putText(imgContours2, '{}cm'.format(nH), (x - 70, y + h // 2), cv2.FONT_HERSHEY_COMPLEX_SMALL, 1,
                        (255, 0, 255), 2)

12. Display the result image and the original image, and wait for any key to be pressed to close the window.

?
cv2.imshow('background', imgContours2)

cv2.imshow('Original', img)
cv2.waitKey(0)

?

Three, result display

Four, application prospects

  1. Industrial measurement: In the industrial field, Opencv dimensional measurement can be used to detect whether the size of parts meets the specifications. For example, on the production line, you can take pictures of parts and use Opencv to measure the length, width, diameter and other parameters of the parts to ensure product quality.

  2. Medical imaging: Opencv size measurement can be used in the field of medical imaging, such as measuring tumor size, blood vessel diameter, etc. in medical imaging such as CT and MRI. This is very important for doctors to help them make accurate diagnoses and treatment plans.

  3. Building measurement: In the fields of construction and real estate, Opencv dimensioning can be used to measure the size of buildings, room areas, etc. By taking photos of buildings and using Opencv for measurements, architects, designers and real estate developers can help with planning and design.

  4. Vehicle measurement: Opencv dimension measurement can be used in the transportation field, such as measuring the length, width, height, etc. of vehicles. This is very important for road design, bridge design, parking lot planning, etc.

  5. Education and training: Opencv dimension measurement can be used in the field of education and training, such as measuring the size and weight of objects in physical experiments. By using Opencv for measurement, students can help students understand and master physical concepts more intuitively.

The knowledge points of the article match the official knowledge files, and you can further learn related knowledge. OpenCV skill tree Home page Overview 23530 people are learning the system