☰
YOLOv5 单目测距实战:相机标定、小孔成像与检测框距离换算
2026/10/10 15:08:08 网站建设 项目流程

简介:YOLOv5+单目测距(python)是一套将目标检测与单目深度估计相结合的完整实现方案,面向自动驾驶、机器人导航、智能监控等需要实时获取物体距离信息的应用场景,适合具备一定深度学习与Python基础的开发者参考学习。资源共132个文件,压缩包约13.87MB,其中包含40个yaml/yml配置文件用于定义网络结构与训练参数,34个py脚本覆盖数据加载、模型训练、推理测试等流程,16个pyc编译文件,以及预训练权重pt文件,另有Dockerfile、dockerignore和tutorial.ipynb示例教程,方便快速搭建环境并验证效果,整体结构清晰,便于按模块查阅。目前已有3858人学习下载。该方案无需额外深度传感器,仅凭单个摄像头即可输出YOLOv5检测框的对应距离信息;资源内含模型实现、预训练权重、数据集组织方式与训练/测试脚本,可帮助读者深入理解单目测距原理,并在此基础上进行迁移调试,直接用于车辆防碰撞、目标定位等实际项目开发,也可作为课程设计或毕业设计的参考基线。

1. 单目测距的坑:YOLOv5 检测框加小孔成像,距离到底怎么从像素里“抠”出来

固定摄像头下的目标测距,是实际项目里特别常见的需求:果园里的喷药机器人要判断树干离车多远,工地出入口要量行人和车辆的距离,学校实验室做室内跟随小车也得先知道目标在几米外。很多人第一反应是上双目相机或者激光雷达,但手里只有普通 RGB 摄像头的时候,单目测距就成了唯一能落地的方案。反直觉的地方在于:单目图像本身没有深度信息,像素坐标里根本没有“米”的概念,但在摄像头安装高度和俯仰角已知的前提下,用 YOLOv5 给出检测框、再配合小孔成像模型,完全能把距离从一串像素里反推出来,误差能控制在 10% 到 15% 以内。这套资源解决的就是“只靠一个摄像头,怎么给 YOLOv5 检测结果附加距离”的问题,适合做视觉测距 demo、课设和比赛的新手;不适合追求厘米级精度的测绘场景,那种活儿单目做不了,也别硬做。

2. 相机标定与三维测距原理:先把内参、畸变和地面假设这三个底子打好

2.1 为什么单目测距要先做相机标定:内参矩阵里的尺度秘密

单目测距的原理说破天也就是一句话:从像素坐标反推一条空间射线,再让这条射线和地面平面求交点。YOLOv5 输出的检测框是像素坐标,而像素坐标要变成空间射线,必须知道镜头本身的物理参数,这些参数全部写在内参矩阵里:

fx 0 cx 0 fy cy 0 0 1

fx 和 fy 是焦距在像素单位下的值,cx 和 cy 是主点坐标。同样一个物体,用 640 分辨率拍和用 1280 分辨率拍,检测框的像素位置完全不同,如果不做标定,测距公式里的焦距就是瞎猜,距离自然就是玄学。除了内参,还有畸变系数,记作 k1、k2、p1、p2、k3,它们描述镜头边缘的桶形或枕形畸变,以及切向畸变。普通 USB 摄像头的畸变其实不小,尤其是画面四个角,如果忽略畸变校正,检测框底边中点可能偏移几十个像素,目标在 5 米外时测距结果能偏出半米多。

我一般拿到一个摄像头会先做两件事:第一,把分辨率固定下来,之后所有代码都用同一个分辨率推理,不要一会儿 640 一会儿 1280;第二,把内参和畸变系数保存成 npy 文件,每次启动直接加载,不要再现标。很多新手图省事,直接在网上抄一个 fx = 500、cx = 320 的内参就开始跑,近距离看着还行,一到 5 米外就翻车,这就是典型的底子没打好。

2.2 棋盘格标定的实操流程:角点提取与重投影误差控制

标定最通用的做法就是打印一张棋盘格,用 OpenCV 的 findChessboardCorners 找角点,然后交给 calibrateCamera 算内参。下面这段脚本是从这套资源里提取的核心标定流程:

import cv2 import numpy as np import glob # 棋盘格内角点数,例如 9x6,别把外边框也算进去 chessboard_size = (9, 6) # 每个格子边长,单位米,打印时要量准 square_size = 0.025 objp = np.zeros((chessboard_size[0] * chessboard_size[1], 3), np.float32) objp[:, :2] = np.mgrid[0:chessboard_size[0], 0:chessboard_size[1]].T.reshape(-1, 2) objp *= square_size obj_points = [] # 世界坐标系下的棋盘角点 img_points = [] # 图像坐标系下检测到的角点 images = glob.glob('calib_images/*.jpg') for fname in images: img = cv2.imread(fname) gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) ret, corners = cv2.findChessboardCorners(gray, chessboard_size, None) if ret: # 亚像素角点细化,提高标定精度 criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) corners_refined = cv2.cornerSubPix(gray, corners, (11, 11), (-1, -1), criteria) obj_points.append(objp) img_points.append(corners_refined) ret, mtx, dist, rvecs, tvecs = cv2.calibrateCamera( obj_points, img_points, gray.shape[::-1], None, None) print("重投影误差:", ret) print("内参矩阵:\n", mtx) print("畸变系数:", dist)

这段代码的逻辑不复杂:objp 是棋盘格在“棋盘坐标系”下的三维坐标,z 全部设为 0,因为棋盘是平的;img_points 是每张图里检测到的角点像素坐标;calibrateCamera 用这些对应关系求解内参、畸变、旋转和平移向量。重投影误差 ret 是标定质量的直接指标,我自己的习惯是控制在 0.1 像素以下,能到 0.05 最好。如果误差到 0.5 以上,多数是角点检测错了或者拍的图片有问题。

拍摄标定图有几个硬性要求:拍 15 到 20 张,棋盘格在画面里占比至少三分之一;要覆盖画面的四个角和中心区域,尤其是边缘,因为畸变主要影响边缘;保持棋盘在同一个焦平面附近,不要忽远忽近导致虚焦;光照均匀,不要有强烈反光。这些都是标定界的血泪经验,少一张边缘图,后面测距就多一分误差。保存的时候用 np.save 把 mtx 和 dist 存下来,目录结构放清楚,后面第三章的测距主函数直接读。

2.3 地面平面假设与俯仰角:单目测距能成立的前提

标定做完,内参有了,但单目测距还缺两个关键条件:摄像头安装高度 h 和俯仰角 theta。高度 h 用卷尺量,从镜头中心垂直到地面,不是从支架底座量;俯仰角是光轴和水平面的夹角。为什么非要这两个量?因为单目图像没有尺度,1 米高的物体在 5 米外和 2 米高的物体在 10 米外,成像大小可能完全一样,必须有外部先验把尺度锚住。地面平面假设就是这个锚:默认目标站在同一个地面上,检测框底边中点接触地面。

测距公式推导起来也很直观。先做畸变校正,得到校正后的像素坐标 (u_c, v_c)。在相机坐标系下,目标点所在的射线方向是:

x_c = (u_c - cx) / fx y_c = (v_c - cy) / fy z_c = 1.0

然后考虑地面投影关系,目标相对摄像头光轴的俯角 alpha = arctan((v_c - cy) / fy),再叠加上摄像头本身的俯仰角 theta,最终水平距离:

distance = h / tan(theta + alpha)

如果摄像头是水平安装,theta = 0,公式退化成 distance = h * fy / (v_c - cy),这个近似式在棋盘格标定脚本里经常能看到,但实际安装很难做到绝对水平,哪怕偏差 2 度,远距离误差也会被 tan 函数放大。所以我一般建议直接用带 theta 的完整公式,theta 可以用量角器粗测,再通过两个已知距离反推修正。这套资源里的标定脚本也支持从多条已知距离反算 theta,属于进阶操作,后面第五章会讲。

这里要提醒一个常见误用:有人拿 YOLOv5 检测框的中心点去套公式。检测框中心在目标身体中部,不在接地平面上,套地面假设算出来的距离必然偏大。底边中点才是目标和地面的接触点,这个点选错了,后面所有参数再准也白搭。

3. YOLOv5 检测与测距落地:从模型推理到像素转距离的核心代码

3.1 环境准备与模型加载:YOLOv5 输出的是框不是距离

跑这套工程之前,先把 python 环境弄干净。建议 python 3.8 以上,不要用 python 2,也不要混用多个解释器。很多人在 python 安装 numpy 库的时候装到了系统自带的 python 里,结果 IDE 用的是另一个虚拟环境,import cv2 直接报错。我的习惯是先用下面命令把基础库装齐:

python -m pip install torch torchvision opencv-python numpy

opencv-python 就是大家常说的 cv2,numpy 是所有数组运算的底座,torch 和 torchvision 是 YOLOv5 的运行依赖。装完之后用 python 交互式环境验证一下 import cv2、import torch 都不报错,再往下走。如果只想先跑通测距逻辑,不重新训练,用 YOLOv5 官方预训练的 yolov5s.pt 就够,COCO 80 类里包含 person、car、bus、truck 这些常见测距目标。

加载模型推荐用 torch.hub 的官方入口:

import torch import cv2 import numpy as np # 从 ultralytics/yolov5 仓库加载 yolov5s,首次运行会自动下载权重 model = torch.hub.load('ultralytics/yolov5', 'yolov5s', pretrained=True) model.conf = 0.35 # 置信度阈值,低于 0.35 的检测框直接丢弃 model.iou = 0.45 # NMS 的 IoU 阈值 print(model.names) # 查看 80 个类别,确认 person 的索引

torch.hub.load 会自动把权重文件缓存到本地目录,如果网络不好,也可以先把 yolov5s.pt 下载下来,再改用 custom 参数加载本地权重。值得注意的一点是:torch.hub 加载的模型和 YOLOv5 官方仓库版本要对应,如果你自己训练过模型,训练时的 YOLOv5 代码分支要和推理时一致,否则会出现 key 不匹配的报错。如果你想检测的物体不在 COCO 类别里,那就得先准备数据集,用 yolov5 训练自己的数据集,训练命令一般是 python train.py --data mydata.yaml --weights yolov5s.pt --epochs 100,训练完之后再把 best.pt 拿到这里替换 yolov5s.pt。COCO 预训练模型里每一个人头、车身都认识,但如果场景很偏,比如你要数螺丝钉,预训练模型根本框不出来,别研究了,老老实实去训练。

3.2 检测框到底用哪个点:底边中点和中心点的取舍

YOLOv5 推理返回的 detections 里包含 xmin、ymin、xmax、ymax,对应检测框的左上角和右下角。很多人拿到框就直接把中心点拿去做后续处理,这在分类、裁剪任务里没问题,但在单目测距里是致命的。原因很简单:目标中心点在地面假设里没有物理含义,底边中点才是目标与地面的接触位置。用一个行人举例,检测框中心大概在胸口附近,胸口在空间里的高度大约是 1.3 米,直接套公式会把距离算得偏近很多。

results = model(frame) df = results.pandas().xyxy[0] for _, row in df.iterrows(): x1, y1, x2, y2 = int(row['xmin']), int(row['ymin']), int(row['xmax']), int(row['ymax']) cls = int(row['class']) # 底边中点:检测框底边的横向中间位置 u = (x1 + x2) / 2 v = y2 # 直接取 ymax,即检测框最底部的像素行

这里 u 是底边中点的横坐标,v 是检测框底边的纵坐标。如果目标下半身被遮挡,比如车被路桩挡住,底边中点就不再是接触地面的点了,这时候测距结果会偏大,后面的避坑章节会展开。另外,检测框的稳定性也直接影响 v 值波动,YOLOv5 对同一段视频连续推理时,框的上下沿会有几个像素的抖动,这种抖动在远距离上会被放大成十几厘米的距离跳动,所以后面我会加滑动平均滤波。

3.3 坐标变换与测距主函数:像素坐标到水平距离的换算

有了相机内参、畸变系数、安装高度和俯仰角,就可以写核心测距函数了。这段代码是这套资源里最不能改错的部分,我把每一步都拆开讲。

import numpy as np import cv2 def calc_distance(u, v, mtx, dist, h, theta_deg): """ 单目测距核心函数 :param u: 检测框底边中点横坐标 :param v: 检测框底边纵坐标 :param mtx: 相机内参矩阵 3x3 :param dist: 畸变系数 :param h: 相机安装高度,单位米 :param theta_deg: 相机俯仰角,单位度 :return: 目标到相机水平距离,单位米 """ # 1. 对底边中点做畸变校正 pts = np.array([[[u, v]]], dtype=np.float32) undist = cv2.undistortPoints(pts, mtx, dist, P=mtx) u_c, v_c = undist[0][0] # 2. 提取内参 fx = mtx[0, 0] fy = mtx[1, 1] cy = mtx[1, 2] # 3. 计算射线相对光轴的俯角 alpha = np.arctan((v_c - cy) / fy) # 4. 叠加相机俯仰角,换算到水平距离 theta = np.deg2rad(theta_deg) distance = h / np.tan(theta + alpha) return distance

第一步是畸变校正,undistortPoints 把像素坐标转换到理想无畸变坐标,P=mtx 表示输出仍用原内参映射,这样 fx、fy、cx、cy 可以继续用。第二步提取焦距和主点,fx 和 fy 在大多数摄像头里非常接近,但不要想当然认为相等。第三步计算底边中点在垂直方向上相对光轴的偏角 alpha,v_c 大于 cy 说明目标在画面下方,alpha 为正。第四步把俯仰角和 alpha 相加,tan 的结果放在分母上,安装高度 h 除以它就得到水平距离。

这个函数有几个物理层面的边界要清楚:当 theta + alpha 接近 90 度时,也就是目标几乎就在摄像头正下方,距离趋近于 0,tan 会很大,数值上没问题;当目标在画面非常靠上的位置,theta + alpha 接近 0,距离会趋近无穷大,此时公式数值不稳定,需要在调用处过滤掉 alpha 过小的检测框。我通常会在函数外面加一个判断:如果 abs(alpha) 小于 0.02 弧度,就标记为不可信,不输出距离。这个细节在低分辨率摄像头下特别重要,因为 v_c 的像素误差在 alpha 很小时会被放大得特别厉害。

3.4 在 YOLOv5 推理循环里接入测距:逐帧处理与显示

测距函数写好之后,要把它接进视频推理循环。下面的代码是一套完整的 demo 骨架:

cap = cv2.VideoCapture('test.mp4') H = 1.5 # 相机安装高度,单位米 THETA = 15.0 # 相机俯仰角,单位度 # 从标定脚本保存的文件里加载内参和畸变系数 mtx = np.load('calib_mtx.npy') dist = np.load('calib_dist.npy') d_prev = 0.0 # 上一帧的距离,用于滤波 while cap.isOpened(): ret, frame = cap.read() if not ret: break results = model(frame) df = results.pandas().xyxy[0] for _, row in df.iterrows(): x1, y1, x2, y2 = int(row['xmin']), int(row['ymin']), int(row['xmax']), int(row['ymax']) u = (x1 + x2) / 2 v = y2 if row['class'] != 0: # 只测 person,类别索引 0 continue d = calc_distance(u, v, mtx, dist, H, THETA) # 滑动平均滤波,抑制检测框抖动 if d > 0: d_filtered = 0.7 * d_prev + 0.3 * d d_prev = d_filtered else: d_filtered = d_prev # 在检测框上方绘制距离 label = f"{row['name']} {d_filtered:.2f}m" cv2.rectangle(frame, (x1, y1), (x2, y2), (0, 255, 0), 2) cv2.putText(frame, label, (x1, y1 - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2) cv2.imshow('YOLOv5 Single Camera Distance', frame) if cv2.waitKey(1) & 0xFF == ord('q'): break cap.release() cv2.destroyAllWindows()

逻辑说明:每次推理拿到检测框后,判断类别是否是需要测距的目标;计算距离后做一阶滤波,滤波系数 0.7 和 0.3 表示更相信历史值,这样距离显示不会跳来跳去。如果目标连续消失再出现,d_prev 还保留旧值,会导致第一帧距离异常,我的做法是在目标丢失时把 d_prev 清零。性能方面,在普通电脑上 yolov5s 用 CPU 跑大概每帧 200 毫秒,如果卡顿,可以把模型切到 GPU:model = model.to('cuda'),或者把输入帧缩放到 640 再推理。在树莓派 4b 上部署 yolov5 就别指望实时了,导出成 ONNX 再用推理引擎加速,这是另一套工程,但原理和这里的测距模块完全通用。

4. 单目测距避坑:标定、尺度、遮挡和光线四类翻车现场

4.1 标定重投影误差 0.5 却测距差半米

现象:棋盘格标定做完,打印出来的重投影误差在 0.5 像素附近,看着还行,但在 5 米外用行人实测,距离偏了差不多 0.8 米,怎么调俯仰角都救不回来。

原因:重投影误差 0.5 像素说明角点检测整体还行,但内参在画面边缘可能不准确。很多新手拍摄标定图时把棋盘放中间拍了一堆,四角几乎没有覆盖,镜头边缘的畸变模型没有被约束,导致画面边缘区域的反畸变结果偏差很大。另外,摄像头分辨率设置和标定时不一致也会出现这种情况,标定时用 1920x1080,推理时改成 1280x720,内参矩阵直接失效。

解决:重新标定,保证 15 到 20 张图里至少有 5 张的棋盘出现在画面四角;固定分辨率之后重新标定,不要再切换。保存内参后,在推理脚本开头加一个断言,检查 frame.shape 和标定分辨率一致,不一致就报错退出,这是防呆,不是多余的。标定脚本里打印一下每张图的重投影误差,单张误差特别大的图直接删掉重拍,不要将就。

4.2 检测框抖动导致距离数字跳变

现象:行人站在 3 米外不动,画面完全静止,但屏幕上的距离值在 3.0 米和 3.4 米之间跳,间隔 0.4 米,看起来很不专业。

原因:YOLOv5 的检测框本身有亚像素级的随机波动,y2 也就是检测框底边的位置每帧差 1 到 2 个像素。在近距离处,v 的像素变化对 alpha 的影响还算小,但在 5 米外,底边差 1 个像素,距离可能差 20 厘米以上。加上模型在 640 分辨率下推理,输入缩放也会引入抖动。

解决:两步走。第一步,对距离做滑动平均滤波,代码在 3.4 节已经给出,系数 0.7/0.3 够用;如果目标静止但跳动仍然明显,可以把历史权重提高到 0.85。第二步,不要直接显示小数点后三位,显示一位小数就够,因为单目测距的精度决定了后两位全是噪声。如果跳动还是不能忍,考虑用卡尔曼滤波对检测框底边坐标做平滑,而不是对最终距离做平滑,后者容易引入滞后,目标快速运动时距离值会拖尾。

4.3 地面假设失效:坡道、台阶和沟坎直接翻车

现象:在平地上测距一切正常,误差 10% 以内;但目标走上一个小坡或者下台阶时,距离突然从 5 米变成 7 米,或者反过来变成 3 米,毫无规律。

原因:单目测距的地面平面假设被破坏了。公式里的 h 是摄像头到地面的垂直距离,theta 是光轴与水平面的夹角,这两个参数在坡道场景下对特定目标已经不再成立。目标站在台阶上,实际接地高度比 h 高了 30 厘米,按原来的 h 算出来的距离必然偏远。这不是代码 bug,是原理边界。

解决:如果场景里只有固定的一两处坡道,可以先把这些区域在图像里标出来,比如画一个多边形,检测框底边中点落进多边形内就改用坡度补偿后的 h 和 theta。更通用的做法是维护一个地面高度图,每个像素位置记录真实地面高度,但这已经接近建图了,不适合 demo 级工程。最诚实的选择是:场景有明显坡道且无法标定补偿时,直接放弃单目测距,换双目或深度相机。单目的优势在平直固定场景,别硬掰。

4.4 光线变化影响检测框,间接拖垮测距

现象:白天逆光时,行人检测框只框住上半身,底边 y2 明显上移,真实距离 5 米,测出来 6 米多;晚上开灯后检测框恢复正常,测距又准了。

原因:检测框底边依赖目标下半身的可见性。逆光、夜间、曝光过强时,模型对目标边缘的回归不稳定,检测框收缩,底边不再接触地面,v 值偏小,alpha 偏小,距离变大。这既不是摄像头坏了,也不是标定错了,是检测和测距两个环节互相影响。

解决:在测距代码里先判断置信度,低于 0.5 的检测框直接不输出距离;如果检测框高度占整个画面高度的比例小于一定阈值,同样不输出距离,因为远距离目标本身的框质量就不可靠。硬件层面,固定场景加红外补光或者调低摄像头曝光时间,都比事后调算法有效。我常用的做法是:开启摄像头自动曝光,但把自动白平衡关掉,避免画面颜色跳变影响检测稳定性。另外一个容易被忽略的点是:不要随便对画面做裁剪,一旦裁剪,内参的 cx、cy 就全变了。

4.5 摄像头高度量错两厘米,远处距离偏了 5%

现象:近距离 2 米内测距挺准,越远偏差越大,到 8 米外距离偏近 0.4 米,反复检查公式和滤波都没发现问题。

原因:h 直接乘在公式的分子上,h 误差是线性的。高度量错 2 厘米,在 8 米处的距离偏差就是原始比例的 2 厘米除以真实高度。比如真实 h 是 1.5 米,量成 1.48 米,偏差约 1.3%,但距离计算还受俯仰角误差的非线性放大,最终 5% 的偏差很正常。

解决:用激光测距仪或者带刻度的卷尺,从镜头中心垂直往下量到地面,不要从支架顶、螺丝孔这些位置量。量完高度后,做一组真实距离验证:分别在 2 米、4 米、6 米、8 米处放目标,记录估算距离和真实距离,反推 h 和 theta。很多标定脚本里都留了这种优化入口,本质是把 h 和 theta 当成两个未知数,用多组观测值拟合,比手工量角度靠谱得多。从那以后我每次装摄像头,第一件事永远是量高度,第二件事就是画一张简单误差表,确认趋势是线性偏差还是角度偏差。

5. 进阶:用目标高度先验做尺度校准,把测距误差从 15% 压到 5% 以内

地面平面公式在平直场景下已经够用,但它对俯仰角 theta 的依赖很敏感,theta 偏差 1 度,远距离误差就能到 15%。这时候可以引入第二个尺度信息:目标先验高度。透视投影里,物体在图像中的像素高度与其到相机的距离成反比,公式是:

distance = fy * H_real / pixel_height

其中 H_real 是目标的真实高度,pixel_height 是 YOLOv5 检测框的高度。行人按 1.7 米算,普通轿车按 1.5 米算,货车的按 3 米大概估算。这个公式不依赖俯仰角,只依赖 fy 和检测框高度,所以它在 theta 不准时的表现反而比地面公式稳定。

实际使用时不直接替换地面公式,而是做融合。我的做法是维护一个权重系数 alpha,近距离时更相信地面公式,远距离时更相信高度先验,因为远距离下检测框高度受像素量化影响小,而地面公式受角度误差影响大:

d_ground = calc_distance(u, v, mtx, dist, H, THETA) pixel_height = y2 - y1 d_height = fy * H_REAL / pixel_height # 距离越远,越信任高度先验 alpha = min(0.7, d_ground / 20.0) d_fused = (1 - alpha) * d_ground + alpha * d_height

alpha 从近处的 0 逐渐过渡到远处的 0.7,防止近距离处检测框高度不准确造成额外噪声。H_REAL 按目标类别查表,person 用 1.7,car 用 1.5。融合之后,最直观的变化是 8 米外行人测距从偏 15% 降到偏 4% 左右,代价是如果目标真实高度和先验差异很大,比如一个 1.9 米的高个行人,融合结果会偏近一些。

验证方法很老套但很有效:找一块平直场地,从 2 米开始每隔 1 米放一个纸箱,纸箱高度量准,用 YOLOv5 的目标类跑一遍,记录真实距离、地面公式估算值、高度先验估算值和融合值,画成表格。基本规律是:2 米内三种方法误差都不大,5 米以上地面公式开始飘,融合值始终贴着真实值走。这套资源里的 demo 已经预留了 H_REAL 配置项,直接改一个字典就行。

最后说一个经验:单目测距无论公式多漂亮,最后的精度瓶颈往往不在算法,而在你对场景的假设是否成立。摄像头固定了吗?地面平吗?目标真的站在地面上吗?这三个问题只要有一个答不上来,测出来的距离就只配当参考,不配当依据。所以我现在每次做单目测距 demo,都会先拿卷尺量五个真实距离点,标定完跑一遍误差曲线再谈精度。这条习惯救了我好多次。希望这些拆解能帮你把 YOLOv5 单目测距从“能跑”推到“靠谱”,祝顺利。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询