用Python+OpenCV打造桌面物体测距神器:从摄像头到咖啡杯的精准测量
每次看到桌面上那杯咖啡,你是否好奇它离摄像头到底有多远?今天我们就用Python和OpenCV,5分钟内搭建一个单目测距系统,让你轻松测量任何桌面物体的距离。无需专业设备,普通USB摄像头即可实现!
1. 准备工作与环境搭建
1.1 硬件与软件需求
要开始这个项目,你只需要准备以下物品:
- 普通USB摄像头(如罗技C920或笔记本内置摄像头)
- 一张标准A4纸(用于摄像头标定)
- 待测物体(如咖啡杯、手机或书本)
软件方面需要安装:
pip install opencv-python numpy1.2 单目测距的核心原理
单目测距基于相似三角形原理,核心公式非常简单:
距离 = (物体实际宽度 × 焦距) / 图像中的像素宽度这意味着我们需要知道:
- 物体的实际物理尺寸(如A4纸宽度为21cm)
- 摄像头焦距(通过标定获得)
- 物体在图像中的像素宽度(通过OpenCV检测获得)
提示:选择A4纸作为标定物是因为其尺寸标准且易于获取,当然你也可以使用其他已知尺寸的物体。
2. 摄像头快速标定实战
2.1 焦距计算步骤
- 将A4纸横向放置在距离摄像头约30cm处
- 拍摄照片并测量A4纸在图像中的像素宽度
- 使用公式计算焦距:
# 示例焦距计算代码 known_distance = 30 # cm known_width = 21.0 # A4纸宽度(cm) pixel_width = 450 # 图像中A4纸的像素宽度 focal_length = (pixel_width * known_distance) / known_width print(f"计算得到的焦距为: {focal_length:.2f}像素")2.2 标定过程常见问题
| 问题现象 | 可能原因 | 解决方案 |
|---|---|---|
| 检测不到A4纸 | 光线不足 | 增加环境亮度或使用辅助光源 |
| 边缘检测不准确 | 背景杂乱 | 使用纯色背景板 |
| 测量结果波动大 | 摄像头自动对焦 | 固定摄像头焦距或使用手动对焦 |
3. 完整测距代码实现
3.1 基础测距脚本
import cv2 import numpy as np # 配置参数 KNOWN_WIDTH = 21.0 # A4纸宽度(cm) FOCAL_LENGTH = 650 # 通过标定获得的焦距(像素) def find_paper_contour(image): gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) edged = cv2.Canny(blurred, 50, 150) contours, _ = cv2.findContours(edged.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) return max(contours, key=cv2.contourArea) if contours else None cap = cv2.VideoCapture(0) while True: ret, frame = cap.read() if not ret: break contour = find_paper_contour(frame) if contour is not None: x, y, w, h = cv2.boundingRect(contour) cv2.rectangle(frame, (x, y), (x+w, y+h), (0, 255, 0), 2) distance = (KNOWN_WIDTH * FOCAL_LENGTH) / w cv2.putText(frame, f"{distance:.1f}cm", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2) cv2.imshow("Distance Measurement", frame) if cv2.waitKey(1) == 27: break cap.release() cv2.destroyAllWindows()3.2 代码优化技巧
- 光照自适应处理:使用动态阈值替代固定阈值
gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2)- 多物体检测:通过轮廓面积筛选不同物体
for contour in contours: if 1000 < cv2.contourArea(contour) < 50000: # 处理符合条件的物体4. 进阶应用与精度提升
4.1 测量任意物体的距离
要测量非A4纸物体,你需要:
- 预先知道物体的实际宽度
- 修改代码中的KNOWN_WIDTH参数
- 调整轮廓检测参数以适应不同物体形状
4.2 提高测量精度的5个技巧
- 固定摄像头位置:使用三脚架或支架减少晃动
- 优化光照条件:均匀的侧光能产生更好的边缘检测效果
- 多次测量取平均:减少单次测量的随机误差
- 定期重新标定:特别是当摄像头位置改变后
- 使用更高分辨率:1080p摄像头比720p精度更高
4.3 实际应用场景扩展
- 智能书桌:自动提醒用户与屏幕的距离
- AR测量工具:结合增强现实技术实现虚拟测量
- 工业检测:小型零件尺寸的快速测量
- 教育实验:物理实验中距离变化的实时监测
在办公室环境中,我将这个系统用于监测显示器与眼睛的距离,当距离小于50cm时会发出提醒,有效缓解了长时间办公带来的视觉疲劳。