如何使用cv2.fisheye.undistortPoints完成畸变与无畸变空间的点坐标转换
核心认知误区
你调用接口得到的结果不符合预期,本质是不熟悉两个函数的输入输出约定:
cv2.fisheye.undistortPoints默认输出的是归一化相机坐标(z=1平面的坐标,没有经过内参缩放平移),不是你需要的无畸变像素坐标,所以会得到负数小数结果。cv2.fisheye.distortPoints要求输入的是无畸变空间的归一化坐标,你直接传入无畸变像素坐标,自然会得到完全偏离的结果。- 你做整图去畸变时给
initUndistortRectifyMap传了R(单位矩阵)和P(和原内参K一致)参数,单点转换时没有对应传入相同参数,也会导致结果不匹配。
正确调用方式
1. 畸变像素坐标 → 无畸变像素坐标
对应你将原图(200,150)转换为去畸变后像素坐标的需求,调用时需要传入和整图去畸变一致的R和P参数:
import numpy as np import cv2 # 你的相机参数 DIM = (953, 720) K = np.array( [ [407.0259762535615, 0.0, 488.89663712932474], [0.0, 409.25366832487896, 388.1998354574297], [0.0, 0.0, 1.0], ] ) D = np.array( [ [-0.04485892302426824], [0.0787884305594057], [-0.08374236678783106], [0.027626067632899026], ] ) # 输入畸变像素坐标,维度要求为Nx1x2 distorted_point = np.array([[[200, 150]]], dtype=np.float32) # 传入和initUndistortRectifyMap一致的R、P参数,直接输出无畸变像素坐标 undistorted_pixel = cv2.fisheye.undistortPoints(distorted_point, K, D, R=np.eye(3), P=K) print(undistorted_pixel) # 输出结果和你观测到的[[[60, 43]]]一致
2. 无畸变像素坐标 → 畸变像素坐标
对应你将去畸变后的(60,43)转换回原图畸变坐标的需求,需要先把像素坐标转成归一化坐标再调用接口:
# 输入无畸变像素坐标 undistorted_pixel = np.array([[[60, 43]]], dtype=np.float32) # 第一步:无畸变像素坐标转归一化坐标(减去主点,除以对应焦距) undistorted_norm = np.zeros_like(undistorted_pixel) undistorted_norm[..., 0] = (undistorted_pixel[..., 0] - K[0, 2]) / K[0, 0] undistorted_norm[..., 1] = (undistorted_pixel[..., 1] - K[1, 2]) / K[1, 1] # 第二步:调用distortPoints得到畸变像素坐标 distorted_pixel = cv2.fisheye.distortPoints(undistorted_norm, K, D) print(distorted_pixel) # 输出结果和你输入的原图坐标[[[200, 150]]]一致
注意事项
- 输入坐标的维度必须为
(N, 1, 2)的浮点类型,否则会出现报错或者异常输出 - 如果你整图去畸变时使用的
P参数和原内参K不一致(比如做了缩放、裁剪),单点转换时undistortPoints的P参数必须和整图去畸变时的参数完全一致才能匹配 - 批量转换大量点时,上述方法的效率远高于遍历
map1、map2查找对应坐标
内容的提问来源于stack exchange,提问作者Kyle
相关产品推荐
相关产品推荐

