【OpenCV】尺寸测量


前言

需要一个已经知道尺寸的物体作为参考。
物体实际宽度/照片中物体的宽度=参考物实际宽度/照片中参考物的宽度
下图左上角方框为2cmX2cm的正方向。
在这里插入图片描述


一、代码分析

Filename: init.py
Usage: This script will measure different objects in the frame using a reference object of known dimension. 
The object with known dimension must be the leftmost object.
Author: Shashank Sharma
"""
from scipy.spatial.distance import euclidean
from imutils import perspective
from imutils import contours
import numpy as np
import imutils
import cv2

# Function to show array of images (intermediate results) 显示图片函数
def show_images(images):
	for i, img in enumerate(images):
		cv2.imshow("image_" + str(i), img)
	cv2.waitKey(0)
	cv2.destroyAllWindows()

img_path = "images/example_02.jpg"#读取图片

# Read image and preprocess
image = cv2.imread(img_path)

gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)#转灰度图
blur = cv2.GaussianBlur(gray, (9, 9), 0)#高斯滤波

edged = cv2.Canny(blur, 50, 100)#获取边缘
edged = cv2.dilate(edged, None, iterations=1)#膨胀
edged = cv2.erode(edged, None, iterations=1)#腐蚀

#show_images([blur, edged])

# Find contours  找轮廓
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

# Sort contours from left to right as leftmost contour is reference object 轮廓排序
(cnts, _) = contours.sort_contours(cnts)

# Remove contours which are not large enough 去掉轮廓面积小的
cnts = [x for x in cnts if cv2.contourArea(x) > 100]

#cv2.drawContours(image, cnts, -1, (0,255,0), 3)

#show_images([image, edged])
#print(len(cnts))

# Reference object dimensions
# Here for reference I have used a 2cm x 2cm square
ref_object = cnts[0]
box = cv2.minAreaRect(ref_object)#最小外接矩形
box = cv2.boxPoints(box)
box = np.array(box, dtype="int")
box = perspective.order_points(box)
(tl, tr, br, bl) = box
dist_in_pixel = euclidean(tl, tr)
dist_in_cm = 2
pixel_per_cm = dist_in_pixel/dist_in_cm  #计算单位长度中的像素个数

# Draw remaining contours
for cnt in cnts:
	box = cv2.minAreaRect(cnt)#最小外接矩形
	box = cv2.boxPoints(box)#4个顶点坐标
	box = np.array(box, dtype="int")
	box = perspective.order_points(box)#以左上、右上、右下和左下的顺序排列方块边框坐标
	(tl, tr, br, bl) = box
	cv2.drawContours(image, [box.astype("int")], -1, (0, 0, 255), 2)
	mid_pt_horizontal = (tl[0] + int(abs(tr[0] - tl[0])/2), tl[1] + int(abs(tr[1] - tl[1])/2))
	mid_pt_verticle = (tr[0] + int(abs(tr[0] - br[0])/2), tr[1] + int(abs(tr[1] - br[1])/2))
	wid = euclidean(tl, tr)/pixel_per_cm 
	ht = euclidean(tr, br)/pixel_per_cm
	cv2.putText(image, "{:.1f}cm".format(wid), (int(mid_pt_horizontal[0] - 15), int(mid_pt_horizontal[1] - 10)), 
		cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)
	cv2.putText(image, "{:.1f}cm".format(ht), (int(mid_pt_verticle[0] + 10), int(mid_pt_verticle[1])), 
		cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 0), 2)

show_images([image])

二、输出结果

在这里插入图片描述

三、参考资料

链接在此


版权声明:本文为linmuquan1989原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。