当前位置: 首页 > news >正文

用Python和YOLOv5给摄像头装上‘尺子’:一个杯子引发的单目测距实战

用Python和YOLOv5给摄像头装上‘尺子’:一个杯子引发的单目测距实战

当你手边只有一个普通的USB摄像头,却想让它具备测量物体距离的"超能力"时,单目测距技术就是你的魔法棒。这个看似高深的计算机视觉应用,其实用生活中常见的物品(比如一个马克杯)就能轻松实现。本文将带你从零开始,用Python和YOLOv5打造一个低成本、高趣味性的单目测距系统。

1. 环境准备与工具选择

在开始之前,我们需要搭建一个稳定的开发环境。推荐使用Python 3.8或更高版本,这个版本在兼容性和性能上都有不错的表现。以下是需要安装的核心库:

pip install torch torchvision opencv-python numpy matplotlib

对于YOLOv5,我们直接从官方仓库克隆最新版本:

git clone https://github.com/ultralytics/yolov5 cd yolov5 pip install -r requirements.txt

注意:如果使用GPU加速,建议安装CUDA 11.3和对应版本的PyTorch以获得最佳性能。

硬件方面,任何一款支持USB3.0的1080p摄像头都能满足需求。我测试使用的是罗技C920,但几十元的普通摄像头同样可以工作。关键在于标定过程的准确性,而不是设备的高端程度。

2. 摄像头标定:用马克杯当标尺

单目测距的核心在于理解相似三角形原理。我们需要先确定摄像头的焦距,这个过程称为标定。具体步骤如下:

  1. 准备一个已知尺寸的物体(如宽15cm的马克杯)
  2. 将物体放置在距离摄像头20cm处并拍照
  3. 使用YOLOv5检测物体在图像中的像素宽度
  4. 通过公式计算焦距:焦距 = (像素宽度 × 实际距离) / 实际宽度
def calculate_focal_length(known_width, known_distance, pixel_width): return (pixel_width * known_distance) / known_width

实际操作中,建议拍摄多组不同距离的照片求取平均焦距值,这样可以减少测量误差。下表展示了我用马克杯标定时的三组数据:

实际距离(cm)像素宽度(px)计算焦距(px)
20320426.67
25256426.67
30213426.00

可以看到,三组数据计算出的焦距非常接近,最终我们取平均值426.44px作为标定结果。这个值将作为后续所有距离计算的基础。

3. 构建完整的测距流水线

有了焦距参数,我们就可以构建完整的测距系统了。系统工作流程分为三个主要步骤:

  1. 物体检测:使用YOLOv5实时检测视频流中的目标物体
  2. 像素测量:获取物体在图像中的包围框宽度(像素单位)
  3. 距离计算:应用相似三角形原理转换像素距离为实际距离

核心计算函数如下:

def calculate_distance(known_width, focal_length, pixel_width): return (known_width * focal_length) / pixel_width

为了提高实用性,我们可以添加一些增强功能:

  • 多物体支持:通过修改YOLOv5的输出处理,可以同时测量多个物体的距离
  • 单位转换:添加厘米/英寸的单位切换功能
  • 历史记录:保存最近几次的测量结果用于对比分析

一个完整的处理帧函数可能长这样:

def process_frame(frame, model, focal_length, known_width): # 使用YOLOv5进行物体检测 results = model(frame) # 解析检测结果 detections = results.pandas().xyxy[0] for _, det in detections.iterrows(): if det['name'] == 'cup': # 只处理目标类别 pixel_width = det['xmax'] - det['xmin'] distance = calculate_distance(known_width, focal_length, pixel_width) # 在图像上绘制结果 cv2.rectangle(frame, (int(det['xmin']), int(det['ymin'])), (int(det['xmax']), int(det['ymax'])), (0,255,0), 2) cv2.putText(frame, f"{distance:.1f}cm", (int(det['xmin']), int(det['ymin'])-10), cv2.FONT_HERSHEY_SIMPLEX, 0.9, (0,255,0), 2) return frame

4. 误差分析与优化策略

在实际测试中,我发现几个主要误差来源:

  1. 角度偏差:当摄像头与物体不在同一水平面时,测量结果会偏大
  2. 镜头畸变:普通摄像头的桶形畸变会影响边缘区域的测量精度
  3. 标定误差:初始焦距测量的准确性直接影响所有后续结果

针对这些问题,可以采用以下优化策略:

  • 多角度标定法:在不同角度拍摄标定物体,建立角度-距离补偿模型
  • ROI限制:只使用图像中心区域进行测量,减少镜头畸变影响
  • 移动平均滤波:对连续视频帧的结果进行平滑处理
# 简单的移动平均滤波实现 class DistanceFilter: def __init__(self, window_size=5): self.window = [] self.size = window_size def update(self, value): self.window.append(value) if len(self.window) > self.size: self.window.pop(0) return sum(self.window) / len(self.window)

下表对比了优化前后的测量误差(单位:cm):

实际距离原始测量优化后测量
30cm32.4cm30.8cm
50cm56.7cm51.2cm
70cm82.3cm72.6cm

虽然误差随距离增加而增大,但优化后的结果明显更接近真实值。对于日常使用场景,这样的精度已经足够。

5. 创意应用与扩展思路

掌握了基础的单目测距技术后,可以尝试许多有趣的扩展应用:

  • 智能货架监控:实时监测货架上商品的取放情况
  • 互动艺术装置:根据观众距离变化产生不同的视觉效果
  • 简易3D扫描:结合物体移动轨迹重建粗略的3D模型

一个特别实用的扩展是距离警报系统,当物体进入预设的危险距离时会发出警告:

def distance_alert(frame, distance, safe_distance=50): if distance < safe_distance: cv2.putText(frame, "WARNING: Too close!", (50,50), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0,0,255), 3) # 可以添加声音报警 # import winsound # winsound.Beep(1000, 200) return frame

在实现这些扩展功能时,记得考虑以下几点:

  1. 性能优化:对于实时应用,可以考虑使用YOLOv5s等轻量级模型
  2. 多线程处理:将图像采集、处理和显示放在不同线程提高响应速度
  3. 用户界面:添加简单的GUI让非技术人员也能方便使用
# 简单的多线程处理示例 import threading class VideoProcessor: def __init__(self): self.frame = None self.running = True def capture_thread(self): cap = cv2.VideoCapture(0) while self.running: ret, self.frame = cap.read() def process_thread(self): while self.running: if self.frame is not None: processed_frame = process_frame(self.frame.copy()) cv2.imshow('Result', processed_frame) if cv2.waitKey(1) == ord('q'): self.running = False

6. 实战技巧与常见问题解决

在实际开发过程中,我总结了一些有价值的经验:

  • 光照条件:过强或过弱的光线都会影响检测精度,建议在均匀光照环境下使用
  • 物体选择:高对比度的纯色物体检测效果最好,避免使用图案复杂的物品
  • 摄像头固定:测量时保持摄像头稳定,手持会导致结果波动

遇到检测不稳定的情况时,可以尝试以下调试步骤:

  1. 检查YOLOv5的置信度阈值(默认0.25),适当提高可减少误检
  2. 验证标定过程是否正确,特别是实际距离的测量要精确
  3. 测试不同分辨率,有时降低分辨率反而能提高检测稳定性
# 调整YOLOv5的检测参数 model.conf = 0.5 # 置信度阈值 model.iou = 0.45 # IOU阈值

对于想进一步深入学习的开发者,推荐探索以下方向:

  • 立体视觉:尝试用两个摄像头实现更精确的测距
  • 深度学习:训练自定义的物体检测模型提高特定场景的准确率
  • 传感器融合:结合红外或超声波传感器提升系统鲁棒性

在项目开发过程中,版本控制也很重要。我习惯使用如下目录结构:

mono_distance/ ├── configs/ # 配置文件 ├── data/ # 测试图像和视频 ├── models/ # 训练好的模型 ├── utils/ # 工具函数 ├── main.py # 主程序 └── requirements.txt # 依赖库
http://www.gsyq.cn/news/1418111.html

相关文章:

  • 从P波到T波:如何用Python+OpenCV给心电波形图做“自动体检”?
  • 微波定向耦合器:原理、指标、架构与设计实例
  • 保姆级教程:在Ubuntu 20.04上从源码编译运行Cartographer ROS(含常见错误排查)
  • 北京APP定制开发费用构成与行业选型综合研究
  • 别再只懂Apriori了!用Python手写一个超市购物篮分析,从牛奶面包数据里挖出隐藏的关联规则
  • Arduino与Visuino实现电机定时启停:可视化编程与L298N驱动详解
  • 据说刷一个百度热搜的成本在1万以上
  • 面向美区市场直播拍卖,跨境网络链路选型全指南
  • Mapillary Vistas数据集实战:用Python快速加载并可视化66类街景语义分割标签
  • 别再只算欧氏距离了!用Python+NumPy实战Grassmann流形,搞定人脸识别中的子空间比对
  • CentOS 7最小化安装后,5分钟搞定网络连接(含nmtui图文详解与常见坑点)
  • 口碑好的卡盒哪个创新强
  • 【ChatGPT汇报材料优化黄金法则】:20年高管秘书亲授——3类高频废稿+5步AI精修法,今日不学明天被退回
  • 保姆级教程:在Ubuntu 20.04上从零跑通《视觉SLAM十四讲》所有代码(附避坑指南)
  • 2026年5月早教中心室内玩具厂家推荐榜:儿童体适能器材、感统训练教具、跑酷套装、攀爬系列、体操垫厂家选择指南 - 海棠依旧大
  • 腾讯云代理商:腾讯云一键部署Hermes Agent 75个技能免配置开箱即用
  • 农业数字化|玉米地田间作物识别数据集|幼苗出苗率|杂草识别|YOLO格式|AI智能农田应用
  • 2026年5月口碑好的深圳居民搬家公司找哪家厂家推荐榜,居民搬家/单位搬迁/日式搬家/搬厂/贵重物品搬运厂家选择指南 - 海棠依旧大
  • 4 构建Agentic AI的实用技巧
  • AI 幻觉杀死了我的生产环境:LLM 输出校验的 6 层防御机制与兜底方案设计
  • Microchip SAM-ICE与Keil µVision调试配置指南
  • 2026年5月评价高的安阳防爆电机公司如何选厂家推荐榜,YBZ系列、YBK系列、矿用隔爆型、粉尘防爆型电机厂家选择指南 - 海棠依旧大
  • 电源箱厂家排行:深圳哪家最靠谱?
  • 告别Edge兼容模式!Win11里找回那个熟悉的IE图标,搞定老旧系统登录
  • CoreSight ELA-600跟踪数据溢出优化方案
  • 车辆线性二,三,四自由度汽车动力学模型稳定性对比仿真【附说明文档】
  • 【石油】基于matlab风化导致的石油有机碳和青藏高原净地质碳收支【含Matlab源码 15573期】
  • 2026 北京 GEO 优化服务商合作参考:客户评价与合规要求深度解析 - 玖叁鹿
  • 用LangGraph构建支持“暂停与人工介入”的长周期任务工作流
  • ST LIS3DHTR代理商