我正在尝试使用 opencv 鱼眼函数将特征从未扭曲空间映射回扭曲空间。 我可以通过以下代码成功地将图像从相机扭曲的鱼眼图像转换为常规空间:
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],
]
)
img = np.zeros((720, 953, 3), dtype=np.uint8)
img = cv2.rectangle(img, (200, 150), (300, 200), (255, 255, 255), -1)
map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K, DIM, cv2.CV_16SC2)
undistorted_img = cv2.remap(
img, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT
)
# The rectangle is now found at 60, 43 in undistorted_img. This code works.
但是,当我想要映射一个点(任一方向)时,我无法使用 cv2.fisheye.un DistorPoints 或 DistorPoints 将点从一个空间移动到另一个空间。 通过使用尺寸为 720 x 953 的图像,我将一个点放在 x,y 200,150 处。 在未失真的图像中,该点现在位于 60,43。 但是,我无法使用任一函数来映射这两点。 这是我的代码和输出:
cv2.fisheye.undistortPoints(np.array([[[200, 150]]], dtype=np.float32), K, D)
# returns array([[[-1.0488918, -0.8601203]]], dtype=float32)
cv2.fisheye.distortPoints(np.array([[[200, 150]]], dtype=np.float32), K, D)
# returns array([[[1064.9419, 822.5983]]], dtype=float32)
cv2.fisheye.undistortPoints(np.array([[[60, 34]]], dtype=np.float32), K, D)
# Returns array([[[-4.061374 , -3.3357866]]], dtype=float32)
cv2.fisheye.distortPoints(np.array([[[60, 34]]], dtype=np.float32), K, D)
# array([[[1103.0706 , 738.13654]]], dtype=float32)
这些都不符合我在图像转换本身中看到的情况。 我对扭曲点和不扭曲点有什么不理解的地方? 谢谢!
我认为你需要估计新的相机矩阵以实现不失真。
points = np.array([[[200, 150]]]).astype(np.float32)
newcameramtx = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(
K, D, DIM, None, balance=1)
dst = cv2.fisheye.undistortPoints(points, K, D, None, newcameramtx)
# [[[323.35104 242.06458]]]
接受的答案会给你错误的结果。
如果不传递 R 和 P 参数,un DistorPoints 将返回标准化坐标。为了得到你期望的结果
points = np.array([[[200, 150]]], dtype=np.float32)
result = cv2.fisheye.undistortPoints(points, K, D, R=np.eye(3), P=K)
print(result) # [[[61.970455 36.19246 ]]] which is what you expect