OpenCV Python solvePnP的EPnP实现与MATLAB官方EPnP输出不一致问题
EPnP算法跨平台实现结果差异排查
测试背景
- 研究方向为计算机视觉领域的solvePnP算法,已获取EPnP算法的MATLAB版本官方实现
- 对比同一测试样例下两套EPnP实现的输出精度与一致性:一套为Python调用OpenCV内置的EPnP求解接口,另一套为Octave兼容MATLAB环境运行的官方EPnP实现
- 测试结果存在异常偏差:两套实现输出的旋转矩阵R前两行所有元素符号完全翻转,平移向量t的数值存在明显差异
测试代码与运行结果
Python端OpenCV EPnP实现
测试代码:
import numpy as np import cv2 cam_in = [[2445.72, 0.0, 819.29], [0.0, 2442.39, 660.13], [0.0, 0.0, 1.0]] # 来自OpenCV的3点测试模型 objPts = [[ 0. , 0. , 0. ], [ 82.5, 0. , 0. ], [165. , 0. , 0. ], [247.5, 0. , 0. ], [ 55. , 27.5, 0. ], [137.5, 27.5, 0. ], [220. , 27.5, 0. ], [ 27.5, 55. , 0. ], [110. , 55. , 0. ], [192.5, 55. , 0. ], [ 0. , 82.5, 0. ], [ 82.5, 82.5, 0. ], [165. , 82.5, 0. ], [247.5, 82.5, 0. ], [ 55. , 110. , 0. ], [137.5, 110. , 0. ], [220. , 110. , 0. ], [ 27.5, 137.5, 0. ], [110. , 137.5, 0. ], [192.5, 137.5, 0. ], [ 0. , 165. , 0. ], [ 82.5, 165. , 0. ], [165. , 165. , 0. ], [247.5, 165. , 0. ]] imagePts = [[648.84735, 335.1484 ], [522.6854 , 317.74222], [400.24448, 301.46362], [281.39792, 285.43964], [560.8046 , 366.6523 ], [437.57022, 349.67358], [318.269 , 333.33557], [598.38196, 415.80203], [475.02866, 397.87906], [354.60062, 380.84167], [636.9289 , 465.04666], [512.3496 , 446.39185], [391.26932, 428.63168], [273.65057, 411.7955 ], [549.6402 , 495.04532], [428.12842, 476.45554], [309.60794, 458.5343 ], [587.5397 , 543.42163], [465.2291 , 524.39795], [346.24826, 505.79684], [624.71814, 591.7365 ], [502.51782, 572.03394], [382.8287 , 552.7545 ], [266.8465 , 534.29364]] cam_in, objPts, imagePts = [np.array(x) for x in [cam_in, objPts, imagePts]] distortion = None ret, rvec, T = cv2.solvePnP(objPts, imagePts, cam_in, distortion, flags=cv2.SOLVEPNP_EPNP) R, _ = cv2.Rodrigues(rvec) print('R') print(R) print() print('T:') print(T)
运行输出:
R [[-0.9553479 -0.10390386 0.27661231] [-0.15995044 0.96896901 -0.18845399] [-0.24844766 -0.22428338 -0.94232199]] T: [[-105.91385446] [-201.18325419] [1596.85002509]]
Octave端官方EPnP实现
测试代码:
clear all close all cam_in = [[2445.72, 0.0, 819.29]; ... [0.0, 2442.39, 660.13]; ... [0.0, 0.0, 1.0]] % 来自OpenCV的3点测试模型 objPts = [[ 0. , 0. , 0. ]; ... [ 82.5, 0. , 0. ]; ... [165. , 0. , 0. ]; ... [247.5, 0. , 0. ]; ... [ 55. , 27.5, 0. ]; ... [137.5, 27.5, 0. ]; ... [220. , 27.5, 0. ]; ... [ 27.5, 55. , 0. ]; ... [110. , 55. , 0. ]; ... [192.5, 55. , 0. ]; ... [ 0. , 82.5, 0. ]; ... [ 82.5, 82.5, 0. ]; ... [165. , 82.5, 0. ]; ... [247.5, 82.5, 0. ]; ... [ 55. , 110. , 0. ]; ... [137.5, 110. , 0. ]; ... [220. , 110. , 0. ]; ... [ 27.5, 137.5, 0. ]; ... [110. , 137.5, 0. ]; ... [192.5, 137.5, 0. ]; ... [ 0. , 165. , 0. ]; ... [ 82.5, 165. , 0. ]; ... [165. , 165. , 0. ]; ... [247.5, 165. , 0. ]]; imagePts = [[648.84735, 335.1484 ]; ... [522.6854 , 317.74222]; ... [400.24448, 301.46362]; ... [281.39792, 285.43964]; ... [560.8046 , 366.6523 ]; ... [437.57022, 349.67358]; ... [318.269 , 333.33557]; ... [598.38196, 415.80203]; ... [475.02866, 397.87906]; ... [354.60062, 380.84167]; ... [636.9289 , 465.04666]; ... [512.3496 , 446.39185]; ... [391.26932, 428.63168]; ... [273.65057, 411.7955 ]; ... [549.6402 , 495.04532]; ... [428.12842, 476.45554]; ... [309.60794, 458.5343 ]; ... [587.5397 , 543.42163]; ... [465.2291 , 524.39795]; ... [346.24826, 505.79684]; ... [624.71814, 591.7365 ]; ... [502.51782, 572.03394]; ... [382.8287 , 552.7545 ]; ... [266.8465 , 534.29364]]; [R T reprojectionPts] = efficient_pnp(objPts, imagePts, cam_in); display(R) display(T)
运行输出:
R = 0.95539 0.10395 -0.27644 0.15990 -0.96902 0.18824 -0.24830 -0.22405 -0.94242 T = -359.306 -80.755 1595.419
核心问题
使用完全一致的测试数据集对比两套EPnP实现时,出现旋转矩阵前两行符号翻转、平移向量数值不匹配的结果,需排查是否遗漏了必要的算法前提或配置参数
内容的提问来源于stack exchange,提问作者rassi
相关产品推荐
相关产品推荐

