双ArUco标记平面夹角测量方案及测试结果疑问
ArUco标记平面夹角测量问题解答
疑问解答
1. 90度场景下composedRvec结果的含义
旋转向量(rvec)的方向代表旋转轴,模长代表旋转角度(单位为弧度)。你测得的(0,1.78,0)结果,代表两个标记的相对旋转轴为y轴,旋转角度为1.78弧度,换算为角度约为102度,和你设置的90度夹角的差值属于位姿估计的正常误差范围。
2. 如何通过composedRvec判断平面夹角是否超过10度
如果仅需要判断平面倾斜偏差,不需要考虑标记在自身平面内的自转,更推荐提取两个标记的z轴法向量计算夹角,也就是你后续优化代码采用的方案。如果要基于composedRvec计算,直接求它的模长即可:
import numpy as np # 计算相对旋转角度(弧度转角度) relative_angle_deg = np.rad2deg(np.linalg.norm(composedRvec)) if relative_angle_deg > 10: print("平面角度偏差超过10度")
注意这个结果会包含标记平面内自转的角度,如果只需要平面倾斜偏差,法向量点积的方案更适配你的需求。
3. 当前使用composedRvec的方案是否正确
方案原理上没有错误,但不适配你的需求。composedRvec计算的是两个标记坐标系的完整3D相对旋转,包含了平面内的自转角度,而你只需要判断两个平面的倾斜夹角,不需要考虑自转,因此用法向量点积计算的方案更合理。
测量值大幅跳变的解决方法
这是ArUco单标记位姿估计的常见问题,对应解决方法如下:
- 放大标记尺寸:你代码中设置的标记边长为0.02m(2cm),过小的标记会放大角点检测误差,导致位姿结果波动大,建议换用边长5cm以上的标记。
- 优化相机标定结果:检查
camera.yml的标定精度,标定需要采集至少20张不同距离、不同角度的棋盘格图像,重投影误差建议控制在0.5像素以内。 - 增加亚像素角点优化:检测到ArUco角点后添加亚像素优化步骤,提升角点定位精度:
# 亚像素角点优化代码,放在detectMarkers之后执行 winSize = (5,5) zeroZone = (-1,-1) criteria = (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.001) for corner in corners: cv2.cornerSubPix(gray, corner, winSize, zeroZone, criteria)
- 添加滑动滤波:对连续多帧的测量结果做平均,过滤随机波动:
# 初始化全局历史角度列表 angle_history = [] window_size = 5 # 每次计算得到angle_degrees后执行 angle_history.append(angle_degrees) if len(angle_history) > window_size: angle_history.pop(0) smooth_angle = np.mean(angle_history)
- 更换位姿估计算法:弃用
estimatePoseSingleMarkers,改用针对平面标记优化的SOLVEPNP_IPPE算法求解位姿,精度提升明显:
# 替换原estimatePoseSingleMarkers的代码 marker_size = 0.02 obj_points = np.array([ [-marker_size/2, marker_size/2, 0], [marker_size/2, marker_size/2, 0], [marker_size/2, -marker_size/2, 0], [-marker_size/2, -marker_size/2, 0] ], dtype=np.float32) success, rvec, tvec = cv2.solvePnP(obj_points, corners[i], matrix_coefficients, distortion_coefficients, flags=cv2.SOLVEPNP_IPPE)
内容的提问来源于stack exchange,提问作者michltm
相关产品推荐
相关产品推荐

