当前位置:首页>python>一起来用OpenCV-Python搞图像处理 | Part.17

一起来用OpenCV-Python搞图像处理 | Part.17

  • 2026-08-27 11:48:09
一起来用OpenCV-Python搞图像处理 | Part.17

第17篇|OpenCV应用案例📏 物体尺寸测量

上一篇我们学习了水印添加与去除技巧,今天我们介绍一个升级场景——物体尺寸测量。无论是工业检测中的小型零件测量,还是日常中的文具、首饰测量,用OpenCV结合参考物,实现测量。

📌 需求分析

  1. 工业检测: 小型零件(如螺丝、垫片、电子元件)的尺寸检测,判断零件是否符合规格;

  2. 日常测量: 文具、首饰、小型生活用品的尺寸测量,拍摄图像,快速获取尺寸;

  3. 电商场景: 商品尺寸标注,用于商品详情页标注。

📌 处理方式

物体尺寸测量的主要逻辑的是「像素比例换算」:

  1. 准备参考物: 放置一个已知实际尺寸的参考物(如1元硬币,直径25mm;尺子,宽度10mm),与目标物体同屏拍摄;

  2. 计算像素比例: 通过轮廓分析,提取参考物的像素尺寸(如硬币的像素直径),计算出“1mm对应多少像素”(像素比例=参考物像素尺寸÷参考物实际尺寸);

  3. 测量目标物体: 提取目标物体的像素大小(长宽),通过像素比例换算为实际尺寸(实际尺寸=目标物体像素尺寸÷像素比例)。

📌 所需处理方法

  • 图像预处理: 高斯滤波去噪、灰度化、二值化,提升轮廓提取的准确性;

  • 轮廓提取: 提取参考物和目标物体的轮廓,筛选有效轮廓;

  • 几何形状分析: cv2.minEnclosingCircle()、cv2.boundingRect()函数,拟合参考物和目标物体的形状,获取像素大小。

📌 完整代码

import cv2
import numpy as np

def measure_object_size(
        img_path: str,
        ref_size: float = 25,
        ref_shape: str = "circle"
):
"""
    物体尺寸测量函数
    :param img_path: 包含参考物和目标物体的图像路径
    :param ref_size: 参考物实际尺寸(mm),默认硬币直径25mm
    :param ref_shape: 参考物形状(circle/rectangle),默认圆形
    """

# 1. 图像预处理
    img = cv2.imread(img_path)
    img_copy = img.copy()
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯滤波去噪
    gray = cv2.GaussianBlur(gray, (5, 5), 0)
# 二值化(自适应阈值)
    _, thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
# 去除细小噪声
    kernel = np.ones((3, 3), np.uint8)
    thresh = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel, iterations=2)

# 2. 提取轮廓
    contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 按纵坐标排序轮廓,让参考物位置在上方
    contours = sorted(contours, key=lambda c: cv2.boundingRect(c)[1])
    contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 1000]

# 3. 计算像素比例(像素/mm)
    ref_pixel_size = 0
for cnt in contours:
# 拟合参考物形状
if ref_shape == "circle":
# 圆形拟合
            (x, y), radius = cv2.minEnclosingCircle(cnt)
            ref_pixel_size = 2 * radius
            cv2.circle(img_copy, (int(x), int(y)), int(radius), (0, 255, 0), 2)
            cv2.putText(
                img_copy,
f"Radius: {ref_size}mm", (int(x)-50, int(y)-20), 
                cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2
            )
break
elif ref_shape == "rectangle":
# 矩形拟合
            x, y, w, h = cv2.boundingRect(cnt)
            ref_pixel_size = w
            cv2.rectangle(img_copy, (x, y), (x+w, y+h), (0, 255, 0), 2)
            cv2.putText(img_copy, f"Width: {ref_size}mm", (x, y-20), 
                        cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 255, 0), 2)
break

# 计算像素比例(1mm对应多少像素)
    pixel_per_mm = ref_pixel_size / ref_size

# 4. 测量目标物体尺寸
for i, cnt in enumerate(contours[1:]):  # 跳过参考物轮廓
# 拟合矩形,获取像素宽度和高度
        x, y, w, h = cv2.boundingRect(cnt)
# 换算为实际尺寸(mm),保留1位小数
        actual_w = round(w / pixel_per_mm, 1)
        actual_h = round(h / pixel_per_mm, 1)

# 绘制目标物体轮廓和尺寸
        cv2.rectangle(img_copy, (x, y), (x+w, y+h), (0, 0, 255), 2)
        cv2.putText(img_copy, f"Size: {actual_w}mm x {actual_h}mm", (x, y-20), 
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)

# 5. 显示结果
    cv2.imshow("Result", img_copy)

    cv2.waitKey(0)
    cv2.destroyAllWindows()

# 调用函数,测量物体尺寸(参考物为硬币,直径25mm)
measure_object_size(
    img_path="object_measure.png",  # 包含硬币和目标物体的图像
    ref_size=25,
    ref_shape="circle"
)

(从实验结果可以看出,计算结果会受到光线干扰的影响,例如下方矩形的光线阴影问题,导致其纵向的宽度计算并不是很精准)

📌 注意事项

  • 测量误差大: 确保参考物和目标物体在同一平面,拍摄时保持镜头垂直于物体,避免倾斜;参考物尽量靠近目标物体,减少光线干扰;

  • 难以提取轮廓: 调整二值化阈值,或增加形态学操作的迭代次数,确保轮廓清晰;

  • 参考物识别错误: 确保参考物是图像中最明显的,或手动指定参考物轮廓;

  • 尺寸显示异常: 检查参考物实际尺寸是否正确。

📌 第17篇小结+下篇预告

本篇我们掌握了物体尺寸测量的技巧,基于像素比例换算,结合参考物,实现了物体大小的测量。

下篇我们讲解本期最后一个OpenCV使用场景——视频人脸模糊。


往期回顾:

为什么文件名不能有“\ / : * ? " < > |”?

Markdown写公式时常见的公式符号

用OpenCV去除图片中的水印 | Part.16

Cookie、Session和Token:你的登录状态为什么会被记住

Markdown的基本语法(五)

最新文章

随机文章