摄像头测量物体大小

需求:

比如给你下面这张图片,测出下面这个黑色块的尺寸大小,并返回黑色块在图像中像素位置的对应坐标
请添加图片描述

代码里面的width是随便给的,就像素与实际大小对应的比例尺寸,可调

代码及注释

from scipy.spatial import distance as dist
from imutils import perspective
from imutils import contours
import numpy as np
import imutils
import cv2


# 中点计算
def midpoint(ptA, ptB):
    return (ptA[0] + ptB[0]) * 0.5, (ptA[1] + ptB[1]) * 0.5


width = 5

# 加载图像,将其转换为灰度
image = cv2.imread('111.jpg')
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
# 高斯平滑,使图像稍微模糊
gray = cv2.GaussianBlur(gray, (7, 7), 0)

# 执行边缘检测,然后执行扩张+侵蚀 闭合对象边之间的间隙(形态学运算移除斑点, 膨胀腐蚀操作)
edged = cv2.Canny(gray, 78, 134)
edged = cv2.dilate(edged, None, iterations=1)
edged = cv2.erode(edged, None, iterations=1)

# 在边缘图中查找轮廓
cnts = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = imutils.grab_contours(cnts)

# 从左到右对轮廓进行排序,并初始化“每公制像素”校准变量
(cnts, _) = contours.sort_contours(cnts)
pixelsPerMetric = None

# 对检测到的所有轮廓进行循环
for c in cnts:
    # 如果轮廓不够大,忽略它,2000是阈值
    if cv2.contourArea(c) < 2000:
        continue
    """ 计算轮廓的旋转边界框"""
    orig = image.copy()
    # 获取最小外接矩阵,中心点坐标,宽高,旋转角度
    box = cv2.minAreaRect(c)
    # 获取矩形四个顶点,浮点型
    box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
    # 数值取整
    box = np.array(box, dtype="int")
    print(box)

    #   对轮廓中的点进行排序,使它们以左上、右上、右下和左下的顺序出现,然后绘制旋转边界框的轮廓
    box = perspective.order_points(box)
    cv2.drawContours(orig, [box.astype("int")], -1, (0, 255, 0), 2)

    # 为符合条件的轮廓绘框
    for (x, y) in box:
        cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)

    #   打开有序的边界框,然后计算左上和右上坐标之间的中点,然后是左下和右下坐标之间的中间点
    (tl, tr, br, bl) = box
    (tltrX, tltrY) = midpoint(tl, tr)
    (blbrX, blbrY) = midpoint(bl, br)

    #   计算左上角点和右上角点之间的中点,然后计算右上角和右下角的中点
    (tlblX, tlblY) = midpoint(tl, bl)
    (trbrX, trbrY) = midpoint(tr, br)

    # 绘制蓝色中间点
    cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
    cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)

    # 在中点之间绘制线,然后将中间点与紫色线连接
    cv2.line(orig, (int(tltrX), int(tltrY)), (int(blbrX), int(blbrY)),
             (255, 0, 255), 2)
    cv2.line(orig, (int(tlblX), int(tlblY)), (int(trbrX), int(trbrY)),
             (255, 0, 255), 2)

    # 计算中点之间的欧几里得距离
    dA = dist.euclidean((tltrX, tltrY), (blbrX, blbrY))
    dB = dist.euclidean((tlblX, tlblY), (trbrX, trbrY))

    # 如果每个度量的像素尚未初始化,则将其计算为像素与提供的度量的比率(在本例中为英寸)
    if pixelsPerMetric is None:
        pixelsPerMetric = dB / width

    # 计算尺寸的大小
    dimA = dA / pixelsPerMetric
    dimB = dB / pixelsPerMetric
    print(dimA)
    print(dimB)

    # 在图像上绘制尺寸大小
    cv2.putText(orig, "{:.1f}cm".format(dimA),
                (int(tltrX - 15), int(tltrY - 10)), cv2.FONT_HERSHEY_SIMPLEX,
                0.65, (255, 255, 255), 2)
    cv2.putText(orig, "{:.1f}cm".format(dimB),
                (int(trbrX + 10), int(trbrY)), cv2.FONT_HERSHEY_SIMPLEX,
                0.65, (255, 255, 255), 2)

    # 显示输出图像
    cv2.imshow("Image", orig)
    cv2.waitKey(0)

结果展示

在这里插入图片描述

  • 1
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

回家种蜜柚

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值