如何利用OpenCV标定的相机参数计算图像中两圆形的真实世界距离
单目像素坐标转真实世界坐标(考虑畸变、相机位姿的高精度方案)
前提:你已完成标定拿到内参矩阵camera_matrix、畸变系数dist_coeffs、外参(旋转矩阵R、平移向量t)、圆形亚像素坐标,默认测量目标处于同一平面(绝大多数平面测量场景适用,若为空间点需额外补充深度约束)
操作步骤
- 第一步:对像素坐标做畸变校正
调用OpenCV的cv2.undistortPoints()直接完成畸变校正,输出校正后的归一化图像平面坐标,示例代码片段:import cv2 import numpy as np # 输入像素坐标,shape为(N,1,2),N是点的数量 pixel_points = np.array([[[x1,y1]], [[x2,y2]]], dtype=np.float32) # 畸变校正,得到归一化坐标 undist_norm_points = cv2.undistortPoints(pixel_points, camera_matrix, dist_coeffs, None, camera_matrix) - 第二步:结合外参求解世界坐标
单目反投影得到的是一条射线,需补充平面约束,这里以最常用的世界坐标系Z=0平面为例(如标定板平面、工件放置平面均可对齐到该平面):
推导逻辑:相机坐标系坐标[Xc, Yc, Zc]^T = Zc * [u_norm, v_norm, 1]^T,其中u_norm、v_norm是校正后的归一化坐标;世界坐标转相机坐标公式为[Xc, Yc, Zc]^T = R @ [Xw, Yw, 0]^T + t,联立消去Zc即可解出对应点的世界坐标[Xw, Yw, 0],也可通过构造单应矩阵直接求解:# 构造投影矩阵 Rt = np.hstack((R, t)) P = camera_matrix @ Rt # 取投影矩阵的第1、2、4列构造单应矩阵H(适配Z=0约束) H = np.column_stack((P[:,0], P[:,1], P[:,3])) H_inv = np.linalg.inv(H) # 逐点计算世界坐标 world_points = [] for p in undist_norm_points: u, v = p[0] p_hom = np.array([u, v, 1]) w_hom = H_inv @ p_hom w_hom /= w_hom[2] world_points.append([w_hom[0], w_hom[1], 0]) world_points = np.array(world_points) - 第三步:计算两点真实距离
拿到两个圆形的世界坐标后,直接计算欧氏距离即可,单位和你标定时候用的世界坐标单位一致(比如标定用毫米做单位,输出距离单位就是毫米):distance = np.linalg.norm(world_points[0] - world_points[1])
精度优化注意点
- 圆形像素坐标建议使用亚像素检测结果,可调用
cv2.cornerSubPix()对圆形中心做亚像素优化,降低检测误差 - 如果你的测量平面不是Z=0平面,只需要把对应平面方程代入第二步的联立公式即可求解
- 外参建议用当前测量场景的实时外参,不要用标定时候的旧外参,避免相机移位带来的误差
内容的提问来源于stack exchange,提问作者mash
相关产品推荐
相关产品推荐

