This is the 27th day of my participation in Gwen Challenge
OpenCV is a C++ library, currently popular computer vision programming library, for real-time processing of computer vision problems, it covers a lot of modules in the field of computer vision. In Python, the OpenCV library is often used for image processing.
This article shows you how to measure the size of an object in an image using OpenCV in Python3.
Measuring Size of Objects in an Image with OpenCV
The principle is introduced
To determine the size of an object in the image, we first need to “calibrate” it with a reference object.
Our reference object needs to have two important properties:
- We should know the dimensions (in width or height) of this object in measurable units (such as millimeters, inches, etc.).
- We should be able to easily find the reference object in the image based on its position (for example, always placing the object in the upper left corner of the image) or by its appearance (for example, unique color), unique and different from all other objects in the image).
In either case, our reference objects should be uniquely identified in some way.
In this case, we will use a quarter dollar coin as the reference object and in all examples make sure it is always the leftmost object in the image, as shown below:
By ensuring that the penny is the leftmost object, we can arrange our object contour region from left to right, grabbing the coin (which will always correspond to the first contour region in the sorted list). And use it to define our pixels_per_metric ratio, which we define as:
Pixels_per_metric = object_width/know_width
A quarter dollar coin is 0.955 inches. Now suppose our object_width (in pixels) is calculated to be 150 pixels wide (based on its associated border).
Therefore, pixels_per_metric is:
Pixels_per_metric = 150px / 0.955in = 157px
Thus, in our image, there are approximately 157 pixels per 0.955 inches.
Using this ratio, we can calculate the size of the object in the image.
Implementation steps
- 1. Transform the original image into grayscale image, gaussian filtering, extract edge and contour;
- 2. Sort the contours from left to right, with the leftmost as the reference;
- 3. Calculate the contour size of the reference object,
pixelPerMetricX
.pixelPerMetricY
; - 4. Calculate the contours of other objects and process them.
The complete code
import numpy as np
from scipy.spatial import distance as dist
import cv2
from imutils import contours
from imutils import perspective
import imutils
def show(name,img):
cv2.imshow(name,img)
cv2.waitKey(0)
cv2.destroyAllWindows()
def midpoint(ptA,ptB):
return ((ptA[0] + ptB[0]) * 0.5 , (ptA[1] + ptB[1]) * 0.5)
img = cv2.imread('E:\\demo\\demo06.png')
width = 25
img = imutils.resize(img,height = 500)
gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
gray = cv2.GaussianBlur(gray,(5.5),0)
edged = cv2.Canny(gray,70.200)
edged = cv2.dilate(edged,None,iterations = 1)
edged = cv2.erode(edged,None,iterations = 1)
cnts,_ = cv2.findContours(edged,cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
(cnts,_) = contours.sort_contours(cnts)
pixelPerMetricX = 0
pixelPerMetricY = 0
order = 1
for c in cnts:
if cv2.contourArea(c) < 100:
continue
orig = img.copy()
box = cv2.minAreaRect(c)
box = cv2.boxPoints(box)
box = box.astype('int')
box = perspective.order_points(box)
cv2.drawContours(orig,[box.astype(int)],0, (0.255.0),2)
for x,y in box:
cv2.circle(orig,(int(x),int(y)),5, (0.0.255),3)
(tl,tr,br,bl) = box
(tltrX,tltrY) = midpoint(tl,tr)
(tlblX,tlblY) = midpoint(tl,bl)
(blbrX,blbrY) = midpoint(bl,br)
(trbrX,trbrY) = midpoint(tr,br)
cv2.circle(orig,(int(tltrX),int(tltrY)),5, (183.197.57), -1)
cv2.circle(orig,(int(tlblX),int(tlblY)),5, (183.197.57), -1)
cv2.circle(orig,(int(blbrX),int(blbrY)),5, (183.197.57), -1)
cv2.circle(orig,(int(trbrX),int(trbrY)),5, (183.197.57), -1)
cv2.line(orig,(int(tltrX),int(tltrY)),(int(blbrX),int(blbrY)),(255.0.0),2)
cv2.line(orig,(int(tlblX),int(tlblY)),(int(trbrX),int(trbrY)),(255.0.0),2Euclidean ((tlblX,tlblY),(trbrX,trbrY)) Euclidean ((tlblX,tlblY))if pixelPerMetricX == 0 or pixelPerMetricY == 0:
pixelPerMetricX = dB / width
pixelPerMetricY = dA / width
dimA = dA / pixelPerMetricY
dimB = dB / pixelPerMetricX
cv2.putText(orig,"{:.1f}mm".format(dimB),(int(tltrX)-10,int(tltrY)),cv2.FONT_HERSHEY_COMPLEX,0.6, (255.255.255),1)
cv2.putText(orig,"{:.1f}mm".format(dimA),(int(trbrX)-10,int(trbrY)),cv2.FONT_HERSHEY_COMPLEX,0.6, (255.255.255),1)
cv2.imwrite('{}.jpg'.format(order),orig)
order += 1
Copy the code
Enter a picture:
The output is:
Imperfections
By simply calculating the size and length of the objects in the graph by ratio, there is bound to be some error. For example, different shooting angles of images will cause certain measurement errors. To get better results, further processing of the image is required.
A series of articles will follow this month,
Wonderful article, please pay attention.