简介基于Python与OpenCV的双目立体视觉项目聚焦图像匹配与测距面向人工智能、通信工程、自动化、电子信息、物联网等专业的在校生和开发者可直接用于毕业设计、课程设计或期末大作业。资源共164个文件压缩包约96.25MB涵盖38个Python源码文件含代码注释上手门槛低、10个UI界面文件、49个BMP图像样本及JPG/XML等辅助资源同时附有CAJ、PDF、DOCX格式的毕业论文与文档资料方便对照设计与撰写报告。项目经过严格调试前后端代码完整部署即可运行功能覆盖图像采集、立体匹配、距离计算等核心环节。目前已有189人学习使用适合需要快速搭建双目视觉演示系统或深入理解算法流程的读者也可在此代码基础上二次开发扩展测距精度优化、目标检测等应用。1. 双目测距是不是智商税先搞清楚这套方案到底能解决什么把两颗普通USB相机固定在支架上让机器人或毕业设计课题拥有“报出前方障碍物距离多少毫米”的双眼这是pythonopencv做双目立体视觉的典型场景。实现路径很直接给左右两路图像找同名点图像匹配再利用三角关系还原深度测距。和单目测距必须知道目标物理尺寸不同双目不需要目标先验和结构光相机比它又不那么怕环境光。室内0.3到3米的测距需求里这是性价比最高的视觉方案之一。很多人以为难点在算法其实这个项目最容易翻车的是标定和参数配合。焦距、基线、畸变属于系统误差SGBM匹配参数则是随机误差两者叠加常让实测精度和想象差一个量级。下面按标定、匹配、测距、误差排查的顺序给出一套可复现的落地流程。适合读这篇的是准备做毕业设计的学生也是想快速搭双目原型的视觉工程师。这篇不聊学术推导只讲能在一个下午跑出首版测距结果的步骤、参数和坑。2. 双目标定棋盘格拍得好不好直接决定测距下限双目测距能不能成立完全建立在两路相机的几何关系已知这个前提上。所以第一件事不是匹配而是标定。标定要解决三件事内参、畸变、外参。内参是像素焦距fx/fy和主点cx/cy畸变是镜头径向和切向的变形外参是右相机相对左相机的旋转R和平移TT的模长就是测距公式里的基线B。只要其中一个没标准后面极线校正和视差计算全都会被污染。2.1 出厂参数为什么不能直接信常见做法是打印A4棋盘格自己标定而不是信任相机出厂参数。理由很简单出厂内参一般只对单目有效双目支架每次装配都会让外参发生变化。就算用固定基线的一体化双目模块温度变化和机械应力也可能让基线产生零点几毫米的偏差这个偏差在3米处会被放大成明显的深度误差。标定时我把棋盘格角点的世界坐标objp乘上实际边长比如格子边长30mm就乘30。这样整个世界坐标系的单位就是mm后面测出来的深度也直接是mm。有人图省事把边长设成1最后深度输出全按“格子”算再乘回去极容易漏这个坑第5章会专门讲。2.2 采集规范别一整版都是同一个姿势采集图片的质量比数量重要。我用9x6内角点棋盘格贴在硬纸板上防止弯曲。拍摄时让棋盘格在画面里占1/3到2/3以左右相机都能完整看到棋盘为前提远近各拍几组。每一组都改变标定板姿态左右转动、前后倾斜、上下移动各来几张倾斜角度别超过20度不然角点检测容易跳到错误位置。数量上15到20对有效图像起步我一般拍25对。采集时左右画面必须同步分辨率锁到同一档尽量关闭相机的自动曝光和自动白平衡。如果相机SDK不支持关闭至少保持环境光照不变。下面这个脚本是我常用的采集工具import os import cv2 os.makedirs(calib/left, exist_okTrue) os.makedirs(calib/right, exist_okTrue) cap_l cv2.VideoCapture(0, cv2.CAP_DSHOW) # Windows后端Linux下去掉CAP_DSHOW cap_r cv2.VideoCapture(1, cv2.CAP_DSHOW) cap_l.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap_l.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) cap_r.set(cv2.CAP_PROP_FRAME_WIDTH, 1280) cap_r.set(cv2.CAP_PROP_FRAME_HEIGHT, 720) idx 0 while True: ok_l, frame_l cap_l.read() ok_r, frame_r cap_r.read() if not (ok_l and ok_r): continue view cv2.hconcat([frame_l, frame_r]) cv2.imshow(stereo capture: s to save, ESC to quit, view) key cv2.waitKey(1) if key ord(s): cv2.imwrite(fcalib/left/{idx:04d}.jpg, frame_l) cv2.imwrite(fcalib/right/{idx:04d}.jpg, frame_r) idx 1 print(saved, idx) elif key 27: break cap_l.release() cap_r.release() cv2.destroyAllWindows()逻辑说明cap_l 和 cap_r 分别打开0号和1号USB相机CAP_DSHOW是Windows上绕开默认后端延迟的常见参数Linux下把第二个参数删掉就行。左右画面拼在一起显示用肉眼确认两路相机都能完整看到棋盘。按s保存时左右文件用相同编号命名后续标定脚本用glob按序号匹配读取避免左右图错位。参数说明1280x720是建议的基础分辨率棋盘在画面里占比太小时角点检测不稳降到640x480虽然算得快但焦距f的像素值变小测距精度跟着下降。分辨率选择要匹配测距范围4.3节会讲像素级视差误差对深度的影响。2.3 标定脚本单目内参与双目外参一次算完采集完成后进入标定。代码顺序是先用findChessboardCorners提角点再用cornerSubPix做亚像素细化然后calibrateCamera求左右内参最后stereoCalibrate联立优化外参。stereoRectify生成极线校正映射表也在这里一并做掉后面匹配和测距直接用映射表remap不用每次重复计算。import cv2 import glob import numpy as np CHECKERBOARD (9, 6) SQUARE_MM 30.0 criteria (cv2.TERM_CRITERIA_EPS cv2.TERM_CRITERIA_MAX_ITER, 30, 1e-4) objp np.zeros((CHECKERBOARD[0] * CHECKERBOARD[1], 3), np.float32) objp[:, :2] np.mgrid[0:CHECKERBOARD[0], 0:CHECKERBOARD[1]].T.reshape(-1, 2) objp * SQUARE_MM objpoints, imgpoints_l, imgpoints_r [], [], [] left_imgs sorted(glob.glob(calib/left/*.jpg)) right_imgs sorted(glob.glob(calib/right/*.jpg)) assert len(left_imgs) len(right_imgs) 0, 左右图片数量不一致 for lf, rf in zip(left_imgs, right_imgs): img_l cv2.imread(lf) img_r cv2.imread(rf) gray_l cv2.cvtColor(img_l, cv2.COLOR_BGR2GRAY) gray_r cv2.cvtColor(img_r, cv2.COLOR_BGR2GRAY) ret_l, corners_l cv2.findChessboardCorners(gray_l, CHECKERBOARD, None) ret_r, corners_r cv2.findChessboardCorners(gray_r, CHECKERBOARD, None) if not (ret_l and ret_r): continue corners_l cv2.cornerSubPix(gray_l, corners_l, (11, 11), (-1, -1), criteria) corners_r cv2.cornerSubPix(gray_r, corners_r, (11, 11), (-1, -1), criteria) objpoints.append(objp) imgpoints_l.append(corners_l) imgpoints_r.append(corners_r) h, w gray_l.shape ret_l, mtx_l, dist_l, _, _ cv2.calibrateCamera(objpoints, imgpoints_l, (w, h), None, None) ret_r, mtx_r, dist_r, _, _ cv2.calibrateCamera(objpoints, imgpoints_r, (w, h), None, None) criteria_stereo (cv2.TERM_CRITERIA_MAX_ITER cv2.TERM_CRITERIA_EPS, 100, 1e-5) ret, mtx_l, dist_l, mtx_r, dist_r, R, T, E, F cv2.stereoCalibrate( objpoints, imgpoints_l, imgpoints_r, mtx_l, dist_l, mtx_r, dist_r, (w, h), criteriacriteria_stereo, flagscv2.CALIB_FIX_INTRINSIC) R1, R2, P1, P2, Q, roi1, roi2 cv2.stereoRectify( mtx_l, dist_l, mtx_r, dist_r, (w, h), R, T, alpha0, newImageSize(w, h)) map1_l, map2_l cv2.initUndistortRectifyMap(mtx_l, dist_l, R1, P1, (w, h), cv2.CV_32FC1) map1_r, map2_r cv2.initUndistortRectifyMap(mtx_r, dist_r, R2, P2, (w, h), cv2.CV_32FC1) np.savez(stereo_params.npz, mtx_lmtx_l, dist_ldist_l, mtx_rmtx_r, dist_rdist_r, RR, TT, EE, FF, QQ, R1R1, R2R2, P1P1, P2P2, map1_lmap1_l, map2_lmap2_l, map1_rmap1_r, map2_rmap2_r) print(stereoCalibrate RMS , ret) print(baseline(mm) , np.linalg.norm(T))逻辑说明整个流程是“角点检测 → 单目标定 → 双目标定 → 极线校正映射表 → 保存参数”。先做单目标定是为了给stereoCalibrate提供每只相机合理的内参初值flagscv2.CALIB_FIX_INTRINSIC表示双目标定阶段固定内参只优化左右相对旋转R和平移T求解更稳定。如果采集图片足够多也可以去掉这个标志让全部参数一起优化但初值不好容易收敛到局部最优我一般先固定内参。参数说明SQUARE_MM必须与实际打印的棋盘格边长一致它决定整个坐标系比例。objp * SQUARE_MM就是把角点世界坐标从“格”换算到“mm”后面Q矩阵输出的三维点也是mm。RMS单位是像素小于0.3像素说明标定质量不错高于0.8建议删掉几组明显失败的图片重跑而不是硬调参数。最后打印的baseline(mm)就是基线B常见小支架在40到120mm之间。注意如果左右相机分辨率在采集过程中改过保存的映射表尺寸会与后续图像不匹配需要统一分辨率后重新生成映射表。2.4 标定结果怎样才算合格RMS只是整体指标我还会做一个极线检查用remap把左右图校正然后在拼接图上画水平线。如果校正正确左右图的同一个角点应该落在同一条水平线上。这个检查耗时不到一分钟却能在匹配前把标定问题暴露出来。import cv2 import numpy as np params np.load(stereo_params.npz) img_l cv2.imread(calib/left/0000.jpg) img_r cv2.imread(calib/right/0000.jpg) rect_l cv2.remap(img_l, params[map1_l], params[map2_l], cv2.INTER_LINEAR) rect_r cv2.remap(img_r, params[map1_r], params[map2_r], cv2.INTER_LINEAR) canvas np.hstack([rect_l, rect_r]) h, w canvas.shape[:2] for y in range(0, h, 50): cv2.line(canvas, (0, y), (w, y), (0, 255, 255), 1) cv2.imwrite(epi_check.png, canvas)逻辑说明把校正后的左右图横向拼接每50像素画一条黄色水平线。理想情况下左图某个角点在右图同一行能找到对应同名角点。如果局部出现明显高度差说明标定板弯曲、某张图片质量差、或左右图像序列没对齐。这一步比RMS更直观建议每次标定后都看一眼这张图。参数说明画线间隔50像素适合720p分辨率画太密看不清画太疏又会漏掉局部畸变区域。3. 立体匹配SGBM 参数不调好视差图就是一张雪花图现在手上有了校正映射表接下来的核心步骤是立体匹配也叫图像匹配把左右图像中的同名点找出来得到视差图。OpenCV里主流有两个匹配器BM快但噪声大SGBM慢一点但稳健不少测距应用我基本默认SGBM。很多人在这一步翻车不是算法复杂而是参数像玄学每个都试一遍太浪费时间。下面给出参数初始值和一套相对清晰的调参逻辑。3.1 极线校正之后匹配从二维降成一维极线校正是承上启下的环节stereoRectify输出R1/R2/P1/P2/QinitUndistortRectifyMap生成映射表remap把左右图拉成“行对齐”状态。此时同名点只存在于同一行立体匹配从二维搜索变成一维搜索左图像素(x, y)只需在右图同一行左侧找相似像素两者横坐标之差就是视差d。视差越大说明目标越近这是“视差”能反过来测距的原因。如果校正没做好SGBM再怎么调参数都救不回来。这就是为什么我把极线检查放在标定阶段而不是匹配阶段。实际项目里校正好坏的判断标准就一句话左图关于水平线对称的视觉特征在右图同一行上能找到对应。3.2 SGBM 参数表先抄这组初始值再调下面是一组1280x720分辨率下的初始值适用于0.3到3米的常规测距场景。我把它当作基准大多数场景在这个基准附近微调就够了。参数作用初始值minDisparity最小视差一般0即可0numDisparities视差搜索范围必须为16的倍数80blockSize匹配窗口边长必须为奇数11P1/P2平滑惩罚系数P2大于P1P183block²P2323block²uniquenessRatio唯一性阈值越大越保守10speckleWindowSize / speckleRange消除小块噪点100 / 32disp12MaxDiff左右一致性检查最大差值1参数说明numDisparities决定能探测到多近的目标它与最近可测距离的关系是dfB/Z。比如f600、B60mm、最近目标0.4m时对应视差90像素numDisparities至少取96。blockSize控制匹配窗口大小窗口越大匹配越稳定边缘越模糊优先试11。P1和P2随block变化P1取83block²P2取323block²这样不同窗口下惩罚量级匹配。uniquenessRatio调大后SGBM会抛弃更多可疑匹配视差图更干净但有效区域变少。3.3 最小匹配代码左右视图到视差图import cv2 import numpy as np params np.load(stereo_params.npz) left_raw cv2.imread(left.jpg) right_raw cv2.imread(right.jpg) left cv2.remap(left_raw, params[map1_l], params[map2_l], cv2.INTER_LINEAR) right cv2.remap(right_raw, params[map1_r], params[map2_r], cv2.INTER_LINEAR) gray_l cv2.cvtColor(left, cv2.COLOR_BGR2GRAY) gray_r cv2.cvtColor(right, cv2.COLOR_BGR2GRAY) block 11 sgbm cv2.StereoSGBM_create( minDisparity0, numDisparities80, blockSizeblock, P18 * 3 * block ** 2, P232 * 3 * block ** 2, disp12MaxDiff1, uniquenessRatio10, speckleWindowSize100, speckleRange32, modecv2.STEREO_SGBM_MODE_SGBM, ) disp sgbm.compute(gray_l, gray_r).astype(np.float32) / 16.0 disp[disp 0] np.nan vis cv2.normalize(disp, None, 0, 255, cv2.NORM_MINMAX).astype(np.uint8) cv2.imwrite(disparity.png, vis) np.save(disp.npy, disp)逻辑说明先把左右原始图用标定阶段的映射表remap成极线校正图再转灰度送入SGBM。disp是SGBM输出类型是int16数值是真实视差的16倍所以必须先转float32再除以16.0。这是最常见的翻车点忘记除以16深度会比真实值小一大截。把非正值置为NaN是为了后续统计深度时直接跳过无效区域。参数说明演示里numDisparities直接写80在f600、B60mm时对应最近约0.45m。如果你的相机参数不一样先用dfB/Z估算一遍。SGBM在720p下耗时大约100到200ms实时性不够时优先降低分辨率而不是盲目缩小numDisparities否则近距离目标直接测不了。如果对实时性不敏感可以再用WLS滤波把视差图平滑一遍cv2.ximgproc.createDisparityWLSFilter(sgbm)效果肉眼可见地提升。但首次跑通不建议加因为WLS又引入几个新参数先让基础流程能稳定出数再做后处理。3.4 视差图上的“洞”是怎么来的视差图里常见黑色空洞来源主要有三类。第一是遮挡。左图看到的区域右图不一定能看到这些区域本来就没有同名点SGBM只能猜猜得离谱时被左右一致性检查判为无效。第二是弱纹理。白墙、桌面这类区域每个像素的匹配代价都差不多唯一性检验不通过直接置为无效。第三是参数过严。uniquenessRatio或speckleWindowSize设得太大会把低置信度区域大面积清零。处理策略是测距时保留这些洞不要做空洞填充。填充出来的深度全是编造数据测距应用里宁缺毋假。如果目标是平面物体可以取ROI内中位数作为结果少量洞不影响统计如果目标是低纹理物体回到3.2节调小uniquenessRatio或者从硬件侧加纹理。4. 从视差到距离用 Q 矩阵把像素差换算成毫米拿到视差图后最后一步就是测距。很多人还在手工写公式、到处猜焦距和基线其实OpenCV的Q矩阵已经把几何关系打包好了。这一章讲清公式、代码单位以及一像素视差误差到底值多少毫米。4.1 三角测距公式depth fB / d双目测距的底层公式是 Z f * B / d。这里的f是校正后左相机投影矩阵P1的[0,0]元素单位是像素B是基线单位mmd是视差单位像素Z的单位与B保持一致。公式本质是相似三角形但落地时真正容易错的是单位。比如标定时objp没有乘格子边长那么T的“mm”实际是“格”Z也会变成格得到结果后想再乘回去这种做法很容易漏乘或错乘。正确做法是一开始就把objp单位定成mm。这里需要和单目测距的常见做法做个对比单目视觉测距比如用solvePnP必须先知道目标物体上若干点的物理尺寸才能反解相机到目标的距离所以会受到目标先验尺寸限制。双目测距完全不需要目标先验尺寸它直接把视差交给Q矩阵输出绝对尺度的三维坐标。代价是必须解决匹配问题低纹理目标在双目里同样测不了。4.2 用 Q 矩阵提取深度ROI 中位数比均值稳import cv2 import numpy as np params np.load(stereo_params.npz) disp np.load(disp.npy) # float32NaN表示无效 # 先补齐无效值避免reprojectImageTo3D出现异常 disp_for_3d disp.copy() disp_for_3d[~np.isfinite(disp_for_3d)] 0 points3d cv2.reprojectImageTo3D(disp_for_3d, params[Q], handleMissingValuesTrue) z_map points3d[:, :, 2].copy() z_map[~np.isfinite(disp)] np.nan # 示例ROI假设目标在(320,240)附近宽高80x80 x, y, w, h 320, 240, 80, 80 roi z_map[y:yh, x:xw] valid roi[np.isfinite(roi)] if len(valid) 0: z_med np.median(valid) z_mean np.mean(valid) print(fROI中位深度: {z_med:.1f} mm, 均值: {z_mean:.1f} mm) else: print(ROI内没有有效视差先回第3章调参数)逻辑说明reprojectImageTo3D输入视差图和Q矩阵输出HxWx3的三维点云第三通道就是Z深度单位mm。handleMissingValuesTrue会把无效点赋一个大数而不是报错所以调用前把NaN置0调用后把原始无效位置回NaN保证统计时不混入假数据。参数说明ROI中位数比均值更适合测距因为视差噪点往往表现为长尾离群值几个错误匹配就能把均值拉偏几十毫米中位数几乎不受影响。如果ROI里有效像素太少不要强行输出深度先回头看SGBM参数是不是把视差图调得太稀疏。4.3 一像素视差误差值多少毫米误差预算表为了对精度有直观感知我算一组误差预算。假设f600像素、基线B60mm那么fB36000。由于∂Z/∂d Z²/(fB)视差差一像素在不同距离处的影响如下表。目标距离Z (mm)B60mm时1像素误差(mm)B120mm时1像素误差(mm)50073.5100028142000111563000250125这张表说明两个规律距离越远同样一像素视差误差造成的深度误差按平方放大基线翻倍误差直接减半。所以提升远处测距精度的思路很明确提高分辨率、扩大基线、或者把SGBM的视差精度从1像素提升到亚像素。这也是为什么很多人把手机摄像头换成小基线USB双目模块后感觉精度变差——不是算法不对是基线太短、分辨率不足。经验选型时基线按最近目标距离的1/10到1/5取。比如最近要测0.3m障碍物基线取30到60mm最近测1m基线可以放到100到200mm。基线太长会导致近处目标左右视野不重叠这个约束往往比精度更优先。5. 排查方向双目测距精度不达标的高频坑如果你照着上面流程跑出来精度仍然不理想先不要怀疑算法按下面五条逐一排查。每条都按“现象 → 原因 → 解决”的顺序写可以直接对照。5.1 标定RMS很小测距却差出好几倍现象stereoCalibrate返回的RMS只有0.2左右但测1m远的物体计算出来是2m甚至3m。原因最典型的是单位写错。objp没有乘格子边长或者格子边长输入与实际打印尺寸不一致。另一种可能是打印时选了“适应页面”软件自动缩放了棋盘比例实际边长比设定值小了5%。解决用游标卡尺量取棋盘格10个格子的总长除以10得到真实边长写进SQUARE_MM后重新标定。这个错误藏得很深因为RMS不随缩放变化视觉上完全看不出来属于双目测距里最容易骗人的玄学问题。5.2 目标边缘出现一圈“毛刺”深度现象视差图上物体轮廓边缘忽近忽远尤其是斜边和细杆边缘像素深度明显偏离物体表面。原因blockSize窗口跨过前景和背景边界窗口内同时包含两种深度匹配代价落在中间位置P2设得太大时还会把边缘视差突变平滑掉。解决blockSize从11降到7或5边缘问题会明显缓解但噪声会略微上升P2相应从323block²降到163block²。如果目标本身纹理丰富可以放心调小窗口。测距取数时把ROI向内收缩几个像素避开边缘轮廓。5.3 低纹理白墙上出现大块黑洞现象对着白墙或浅色桌面SGBM输出几乎全是无效区域视差图成片黑色。原因弱纹理区域每个位置匹配代价都差不多SGBM找不到可靠同名点uniquenessRatio设得越大这种情况越明显。解决低纹理是物理层面的信息缺失不是参数能完全救回来的。常见做法是给目标增加纹理比如贴一张A4纸、放个带LOGO的箱子固定产线上还可以用投影仪打散斑。如果场景不允许改造就不要对纯白区域做测距改为基于边缘或已知尺寸的估计更靠谱。5.4 左右图亮度不一致导致匹配失败现象左边相机画面偏亮右边偏暗视差图半张正常半张是噪点。原因USB相机默认开启自动曝光和自动白平衡两支镜头分别调整导致同一世界点的灰度或颜色在两幅图里不一致代价函数直接失效。解决优先固定相机参数能用相机SDK或V4L2控制就把自动曝光、自动增益、自动白平衡全部关闭手动设置曝光时间做不到时用左图做参考对右图做一次直方图匹配。直方图匹配会有一定副作用对比度会被整体拉伸但比让SGBM面对两幅亮度不一致的图像稳得多。固定曝光才是治本做法。5.5 环境装错anaconda里没有cv2SGBM_create报不存在现象在Anaconda Prompt里输入python后import cv2报ModuleNotFoundError或在vscode里跑同一段代码报AttributeError: module cv2 has no attribute StereoSGBM_create。原因大部分是环境串了。pip把opencv-python装到了base环境脚本却用conda虚拟环境解释器执行还有一种是opencv-python和opencv-contrib-python版本不一致安装顺序互相覆盖导致部分接口消失。解决先确认执行脚本的解释器路径python -c import sys; print(sys.executable)。然后在同一个解释器下安装依赖pip install opencv-python opencv-contrib-python装完打印print(cv2.version)确认。如果目标平台是Linux且想要CUDA版OpenCV自己用CMake编译也能做但SGBM是CPU密集算法CUDA版收益有限新手不建议在这上面花时间。6. 精度验证才是最后一道工序把误差表打印出来整个流程跑通后最后一步是验证。视觉测距的系统误差不像超声波那么稳定我会用卷尺建立一组距离真值把测量结果整理成误差表。这张表既是验收依据也是后续调参的“后悔药”每次改完参数重跑一遍对比误差变化。6.1 12个距离点的误差表脚本import numpy as np # 真值来自卷尺测量值来自上一章的ROI中位深度 truth np.array([400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000]) measured np.array([413, 608, 794, 1018, 1218, 1418, 1623, 1834, 2044]) err measured - truth rel err / truth * 100 for t, m, e, r in zip(truth, measured, err, rel): print(f真值 {t:5d} mm | 测量 {m:6.1f} mm | 误差 {e:6.1f} mm | 相对误差 {r:5.2f}%) # 一次线性拟合把系统性偏差校回来 coef np.polyfit(truth, measured, 1) print(线性补偿系数(a*xb):, coef) corrected np.polyval(coef, truth) print(校正后最大绝对误差/mm:, np.max(np.abs(corrected - truth)))逻辑说明把真值和测量值按距离点对齐打印误差和相对误差。np.polyfit做一次线性拟合如果误差随距离系统性增大用拟合系数可以把大部分偏差校回来。校正公式是measured_comp (measured - b) / a。参数说明测量值建议每个距离点取3到5次记录中位数而不是单次值。真值距离覆盖0.4到2m已经能反映短距离和中等距离的误差趋势。如果你的应用范围超过2m把最远点加到3m甚至5m再跑一遍。6.2 误差表的用途和验收标准用真实数据跑出来的误差表通常长这样真值(mm)测量值(mm)绝对误差(mm)相对误差(%)400413133.2560060881.33800794-6-0.7510001018181.8012001218181.5014001418181.2916001623231.4418001834341.8920002044442.20如果相对误差稳定在3%以内作为毕业设计或产品原型完全够用超过10%就回去查5.1节的单位问题和4.3节的基线合理性。这个误差修正表本身就是毕业论文里“系统误差分析与修正”一节很好的素材建议保留每一轮的原始记录。我的习惯是每次拆装过支架、换过镜头之后都把这个误差表脚本重跑一遍。视觉测量设备永远只有在校准后才可信而不是标定过一次就永久有效。希望帮到你。本文还有配套的精品资源点击获取