简介:这是一份聚焦双目视觉测量精度的毕业设计PDF,适合计算机视觉、图像处理方向的本科生及研究生参考。资源包仅含1个PDF文件,大小5.16MB,内容完整覆盖双目摄像机标定、图像预处理、角点与圆形特征提取、立体匹配等关键流程。作者在传统Harris角点检测基础上提出了借助霍夫变换直线求取角点坐标的改进思路,并针对圆形特征周边灰色区域问题,结合灰度直方图选取合适阈值处理;立体匹配环节则设计了“点-窗口-点”匹配方法,提升了角点匹配准确率。文档同时介绍了基于Matlab实现的测量软件,可计算特征点三维坐标,并通过实际工件验证了精度与效率。目前已有309人学习下载,适合作为毕业论文选题、实验设计或双目视觉入门与进阶的参考资料。 从本科毕设到实际产线,双目视觉测量工件尺寸这条路,我自己完整走下来过一轮,踩过的坑比教程里的代码还多。这篇就把整个流程拆开讲透,包括为什么选Matlab、标定怎么做到误差可控、SGBM参数怎么调才不出“坑坑洼洼”的视差图,以及最后尺寸测量结果怎么验证才靠谱。内容适合正在做相关毕设、课设,或者刚接触机器视觉测量想快速上手的工程师参考。
1. 项目整体思路与技术选型
1.1 为什么选“双目视觉”而不是单目或结构光
测量工件尺寸,很多人的第一反应是用单目相机加标定板,换算像素尺寸。单目方案的痛点是:必须保证工件和标定板在同一平面内,一旦工件有厚度变化或者摆放角度偏一点,测出来的尺寸就失真。结构光方案(比如投射光栅)精度确实高,但硬件成本高、对反光表面不友好,而且不适合所有现场环境。
双目视觉的本质是模仿人眼:两个相机从不同位置拍摄同一工件,通过左右图像的视差计算深度。一旦有了每个像素的三维坐标,测量长、宽、高、孔径、边缘间距都变成了点与点的欧氏距离计算。这套方案最大的优势是非接触、全场测量、对摆放姿态不敏感,工件随便摆,只要在两个相机视野内都能测。精度在近距离场景下(0.3m~1m)可以达到亚毫米级,满足很多工业零件的质检需求。
我当时选择的方案参数如下,供参考:
| 项目 | 参数 |
|---|---|
| 左右相机 | 两个同型号USB工业相机,分辨率1280x960 |
| 镜头焦距 | 6mm定焦,畸变控制较好 |
| 基线距B | 120mm,两个光心之间的水平距离 |
| 工作距离 | 400mm~600mm |
| 标定板 | 12x9棋盘格,方格边长20mm |
| 被测工件 | 矩形铝块、圆形垫片、带孔零件 |
这里建议两个相机务必同型号同批次,否则色彩响应、噪声特性不同,立体匹配时相似度计算会吃亏。
1.2 为什么用Matlab而不用OpenCV或Halcon
Matlab在算法调试阶段的优势是其他平台很难替代的。Computer Vision Toolbox提供了完整的相机标定、立体标定、立体匹配、三维重建函数,calibrator和stereoCameraCalibrator两个App是图形化操作,不用写代码就能拿到标定结果,这对快速验证算法思路非常方便。
有人会觉得OpenCV是免费的,Halcon商业版效果好。但Matlab的独特价值在于:每个步骤都有文档、有例子、有可视化中间结果。比如视差图出来后,可以立刻用imshow配合colormap检查匹配质量;disparitySGM函数可以直接看到左右一致性检查的效果。这对理解算法原理、排查问题非常有帮助,尤其适合毕业设计这种需要“过程清晰、结果可解释”的场景。
Matlab的另一个优点是矩阵运算和脚本调试一体,标定、匹配、三维重建、尺寸计算可以写在一个脚本里整个跑通,无需在不同语言间倒腾数据。
2. 相机标定:整个项目的精度基石
2.1 标定板选择与图像采集要点
标定板我用的是12x9的棋盘格,方格边长20mm。打印后用玻璃板夹平,避免纸张褶皱导致的角点坐标误差。如果你的预算允许,建议买陶瓷或铝基板标定板,热稳定性更好;我这边是实验室打印的,精度也够用,前提是贴平、不能折。
图像采集有四个硬性要求:
- 数量至少15~20对。左图和右图必须同步拍摄,我在程序里用
imaq工具箱做了双相机硬触发同步,没有同步硬件的话,可以用snapshot在两个相机同时抓帧,尽量固定工件和相机不动。 - 标定板姿态必须丰富。要有X方向倾斜、Y方向倾斜、Z方向旋转、远近移动,目的是让标定算法充分解算出内外参数。如果只在一个平面内平移,标定结果会很差。
- 标定板要占画面1/4以上。太小了角点提取精度直接崩。
- 光照均匀。避免标定板上有强烈反光和阴影,不然棋盘格角点检测会跳。
2.2 标定实操与结果评价指标
Matlab里打开stereoCameraCalibrator,加载左右图像对,自动检测棋盘格,逐对确认角点位置,然后点“Calibrate”。几分钟就出结果。
标定结果拿到后,重点看三个指标:
- Mean Reprojection Error(平均重投影误差):最好控制在0.5像素以内,超过0.8像素的标定建议重做。这个值反映了像素坐标与重投影坐标的平均偏差。
- Stereo baseline(基线长度):标定出来的基线应该和你粗测的两个相机光心距离接近。差太多说明标定有问题。
- 畸变系数:径向畸变k1、k2和切向畸变p1、p2。数值本身不敏感,重要的是标定后是否能把畸变矫正干净。
标定完成后,直接导出到工作区,得到左右相机的内参矩阵、畸变向量、旋转矩阵R和平移向量T。注意T的单位是毫米或米,取决于你标定板方格的实际单位。我的方格是20mm,所以T是20.1mm左右,合理。
3. 立体校正与立体匹配:视差计算的灵魂
3.1 立体校正:让左右图像“行对齐”
标定完的下一步是极线校正。什么意思呢?理想情况下,左右相机光轴平行、成像平面共面,那么同一个物体点在左图和右图上的像素只在水平方向有偏移(即视差),垂直方向没有偏移。这样立体匹配时只需要在一维的搜索范围内找对应点,效率和准确率都大幅提升。
Matlab的rectifyStereoImages函数就是干这个的,它基于Bouguet算法,把左右图像重投影到一个共同平面上,输出是行对齐的校正图像对。这一步别跳过,直接拿原始图做匹配也能跑,但匹配效果和视差图质量完全是两个档次。
校验行对齐是否成功,可以在校正后的左图上每隔50行画一条水平线,检查这些线与右图的同一特征点是否相交在同一行上。如果差2~3个像素,一般还能接受;差太多,就回去重新检查标定。
3.2 SGBM匹配参数调试的实战经验
立体匹配的核心函数是disparitySGM(Semi-Global Matching,半全局匹配)和disparityBM。BM速度快但效果粗糙,我用的是SGM,线条和边缘更完整,匹配坑少。
参数分四个,调节优先级从高到低:
| 参数 | 作用 | 我最后用的值 | 经验解读 |
|---|---|---|---|
| NumDisparities | 视差搜索范围 | 128 | 必须是16的倍数;范围越大,计算越慢,但能测更近的物体 |
| BlockSize | 匹配块大小 | 15 | 必须是奇数;太小噪声大,太大边缘被“磨圆” |
| DisparityRange | 最小/最大视差 | [0, 96] | 根据测量距离反推:视差=基线*焦距/深度 |
| UniquenessRatio | 唯一性比例 | 10 | 防止多峰匹配,值越大越严苛,纹理弱时不能太大 |
我最开始用默认参数跑,出来的视差图像一大块“空洞”,尤其在工件边缘和反光区域。后来手动调参,把NumDisparities从64提到128,BlockSize从9提到15,空洞和噪声明显减少。
另外要开左右一致性检查,即DisparityRange里的左右图互相验证,这样能剔除遮挡导致的错误匹配。Matlab的disparitySGM可以设置左右图互换检查,我开了这个选项后,工件边缘处的误匹配点大幅减少。
一个关键细节:视觉测量中,决定尺寸精度的不是视差图整体的“好看程度”,而是工件边缘处的视差值是否连续、是否准确。如果边缘处视差跳变过大,直径测量就会偏。所以我后面还用了imgaussfilt对视差图做轻度平滑(σ=1~2),但绝不重度滤波,否则边缘被抹平。
4. 三维重建与工件尺寸计算
4.1 从视差到三维坐标的数学过程
视差图d(u,v)的含义是:左图(u, v)处的像素,在右图同一行偏移d个像素后找到了匹配对应点。深度和视差的关系很简单:
Z = (f * B) / d
其中f是焦距(像素单位,可以直接取标定结果的fx),B是基线距(单位mm或m),d是视差(单位像素)。注意这里视差和深度是反比关系,物体越近,视差越大,深度越小。
只算出Z还不够,还要还原X和Y。相机坐标系下:
X = Z * (u - cx) / fx Y = Z * (v - cy) / fy
cx、cy是主点坐标。到这一步,每一个像素就都成了一个三维点。Matlab里reconstructScene函数可以直接基于标定结果把视差图像素转为三维点云,但不建议直接拿来算尺寸,因为有畸变的点云会有弯曲变形。我更推荐的做法是:先用标定的内参把视差转深度,再做尺寸计算。
我自己写的关键转换代码逻辑:
function [X, Y, Z] = disparityToPoint(disparity, stereoParams) % 将视差图转换为相机坐标系下的三维点坐标矩阵 % stereoParams.CameraParameters1 为左相机参数 fx = stereoParams.CameraParameters1.IntrinsicMatrix(1,1); fy = stereoParams.CameraParameters1.IntrinsicMatrix(2,2); cx = stereoParams.CameraParameters1.IntrinsicMatrix(3,1); cy = stereoParams.CameraParameters1.IntrinsicMatrix(3,2); B = norm(stereoParams.TranslationOfCamera2); % 基线距 % 避免除零:视差为0或负数的区域置为NaN disparity(disparity <= 0) = NaN; Z = B * fx ./ disparity; [rows, cols] = size(disparity); [uGrid, vGrid] = meshgrid(1:cols, 1:rows); X = (uGrid - cx) .* Z / fx; Y = (vGrid - cy) .* Z / fy; end注意IntrinsicMatrix在Matlab里的排列方向:它是转置矩阵的形式,即fx取(1,1)没错,但cx在(3,1)而不是(1,3)。这个坑我踩过,算出来的坐标镜像错乱,花了一个晚上才定位到。
4.2 工件尺寸测量实现与验证
尺寸测量分两步:第一步,在左图(或校正图)上提取待测特征点的像素坐标;第二步,把这些像素坐标对应到三维点坐标,再计算欧氏距离。
比如测矩形铝块的长边,我先用detectHarrisFeatures或Canny边缘提取出矩形边界,再拟合直线,取两端的交点作为角点,得到左右两个角点像素坐标(u1,v1)和(u2,v2),然后通过上面的三维转换得到两个点的三维坐标P1和P2,最后计算:
L = norm(P2 - P1)
这样得到的就是真正空间中的直线距离,不受工件摆放角度影响。垫片直径的测量也类似,提取圆的轮廓后拟合成椭圆,椭圆中心点的三维坐标可以通过轮廓点的平均深度近似得到,再测量轮廓上相对中心对称两点的距离。
这里有一个容易忽略的问题:在视差图上取边缘点的时候,边缘像素的三维坐标精度是相对较低的,因为立体匹配在边缘处容易受遮挡和纹理不连续影响。我的做法是,取边缘内侧2~3个像素的点做多次采样,然后取中位数。实测下来,比单点取值稳定很多。
验证方面,我用游标卡尺(分辨率0.01mm)测量工件真实尺寸作为基准,和算法结果做对比:
| 工件/尺寸 | 游标卡尺测量值(mm) | 算法测量值(mm) | 绝对误差(mm) |
|---|---|---|---|
| 铝块长边 | 80.02 | 79.68 | 0.34 |
| 铝块短边 | 50.05 | 49.83 | 0.22 |
| 垫片外径 | 30.02 | 30.31 | 0.29 |
| 垫片内径 | 10.03 | 10.22 | 0.19 |
整体误差在0.2mm~0.4mm之间。说实话,这个精度在近距离视觉测量里算正常水平,想压到0.1mm以内,需要更高分辨率的相机、更精密的标定板,以及更稳定的光照环境。
5. 误差来源、常见问题与排查技巧
5.1 误差来源的大致分类
误差分三块。第一是标定误差:标定板不平、图像数量不足、角点检测不准,会直接影响三维重建的整体尺度,典型表现是所有尺寸等比例偏大或偏小。第二是匹配误差:光照不均、表面反光、纹理稀疏,导致视差图局部错误,典型表现是某个尺寸忽大忽小不稳定。第三是算法边缘误差:边缘像素本身的深度精度低,如果不加处理,测量值波动会比较大。
我在实验中用标准量块(已知长度)做了重复性实验:同一个工件、同一个位置,连续测量10次,看测量值的标准差。标准差能反映系统的随机误差,这个指标适合用来评估你的双目系统是否稳定。我的10次测量标准差在0.15mm左右,属于可接受的波动范围。
5.2 实战中踩过的几个坑
坑一:忽略光源色温和亮度一致性。我用普通LED灯照明,发现左图和右图同一个工件表面的亮度差异较大,导致SGBM匹配时相似度计算错误。后来加了柔光罩,并把左右相机的曝光时间设为相同,效果立竿见影,视差图空洞减少了约40%。
坑二:工件表面太亮,反光导致匹配失败。金属零件表面有镜面反射,从左右相机看过去反射点位置不一致,视差图直接出现“洞”。解决方法是适当降低曝光、增加漫反射光,或者在工件表面喷一层显影剂(如果允许接触工件的话)。
坑三:视差搜索范围设置不合理。如果工件到相机的距离范围是400mm~600mm,对应视差范围和距离成反比,最远点的视差最小,最近点视差最大。我把DisparityRange设置过小,导致远距离部分工件直接丢匹配;设置过大,不仅计算慢,还会出现大量“纹波噪声”。建议先做一次粗匹配,统计视差直方图,再根据直方图范围确定合理参数。
坑四:reconstructScene直接输出的三维点有“曲面效应”。原因是畸变矫正后边缘区域的深度误差比中心区域大,整个被测平面会呈现轻微弯曲。处理办法是校正图像的时候也同时用UndistortImage结合OutputView参数,保证像素坐标系和三维坐标系一一对应,不要混用。
这里再补充一个提高测量稳定性的小技巧:测量同一尺寸时,可以采集10帧图像,分别算出10个尺寸值,然后取平均值作为最终结果。这个过程很简单,但能明显削弱随机噪声的影响,校准实验里我把标准差从0.15mm降到了0.06mm左右。
最后再分享一个个人经验:双目测量系统搭建完成后,真正决定精度上限的往往不是算法,而是机械结构。两个相机的相对位置如果不稳定,哪怕只动0.5mm,测量结果也会飘。固定相机一定要用刚性支架,尽量不用可调节的云台;装好后做一次完整的标定,然后整个实验过程中绝对不要再碰相机的位置。如果需要移动工作台,就把工件移走、相机保持不动,重新标定这件事能省就省不了。
这套系统后续还可以扩展的地方不少,比如换更高分辨率相机、引入深度学习立体匹配网络、给工件加边缘模板匹配做自动化测量。不过对于现阶段做毕设或者入门机器视觉来说,先把经典的标定、匹配、三维重建、尺寸计算这条链路跑通,把每个环节的误差来源摸清楚,比堆砌一堆“看起来很高级”的功能有价值得多。
本文还有配套的精品资源,点击获取