前言
需要一个已经知道尺寸的物体作为参考。
物体实际宽度/照片中物体的宽度=参考物实际宽度/照片中参考物的宽度
下图左上角方框为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版权协议,转载请附上原文出处链接和本声明。