gpt4 book ai didi

python - 在 Python 的 OpenCV 中使用鱼眼相机捕获的点不失真的正确方法是什么?

转载 作者:行者123 更新时间:2023-12-02 16:04:19 26 4
gpt4 key购买 nike

信息:

我已经校准了我的相机,发现相机的内在矩阵 (K) 及其畸变系数 (d) 如下所示:

import numpy as np
K = np.asarray([[556.3834638575809,0,955.3259939726225],[0,556.2366649196925,547.3011305411478],[0,0,1]])
d = np.asarray([[-0.05165940570900624],[0.0031093602070252167],[-0.0034036648250202746],[0.0003390345044343793]])

从这里开始,我可以使用以下三行来取消扭曲我的图像:

final_K = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(K, d, (1920, 1080), np.eye(3), balance=1.0)

map_1, map_2 = cv2.fisheye.initUndistortRectifyMap(K, d, np.eye(3), final_K, (1920, 1080), cv2.CV_32FC1)

undistorted_image = cv2.remap(image, map_1, map_2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)

生成的未失真图像似乎是正确的 Left image is distorted, right is undistorted ,但是当我尝试使用 cv2.remap() 来消除图像点失真时,点未映射到与其在图像中对应的像素相同的位置。我使用

检测了左图中的校准板点
ret, corners = cv2.findChessboardCorners(gray, (6,8),cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
corners2 = cv2.cornerSubPix(gray, corners, (3,3), (-1,-1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1))

然后按以下方式重新映射这些点:

remapped_points = []
for corner in corners2:
remapped_points.append(
(map_1[int(corner[0][1]), int(corner[0][0])], map_2[int(corner[0][1]), int(corner[0][0])])
)

In these horizontally concatenated images ,左图显示了在扭曲图像中检测到的点,而右图显示了右图中点的重新映射位置。

此外,我无法使用 cv2.fisheye.undistortPoints() 获得正确的结果。我有以下功能来消除扭曲点:

def undistort_list_of_points(point_list, in_K, in_d):
K = np.asarray(in_K)
d = np.asarray(in_d)
# Input can be list of bbox coords, poly coords, etc.
# TODO -- Check if point behind camera?
points_2d = np.asarray(point_list)

points_2d = points_2d[:, 0:2].astype('float32')
points2d_undist = np.empty_like(points_2d)
points_2d = np.expand_dims(points_2d, axis=1)

result = np.squeeze(cv2.fisheye.undistortPoints(points_2d, K, d))

fx = K[0, 0]
fy = K[1, 1]
cx = K[0, 2]
cy = K[1, 2]

for i, (px, py) in enumerate(result):
points2d_undist[i, 0] = px * fx + cx
points2d_undist[i, 1] = py * fy + cy

return points2d_undist

This image显示使用上述函数去失真时的结果。

(这一切都在 Python 3.6.8 的 Ubuntu 18.04 上的 OpenCV 4.2.0 中运行)

问题

为什么图像坐标的重新映射不能正常工作?我是否错误地使用了 map_1map_2

为什么使用 cv2.fisheye.undistortPoints() 的结果与使用 map_1map_2 的结果不同?

最佳答案

问题 1 的答案:

您没有正确使用 ma​​p_1ma​​p_2

cv2.fisheye.initUndistortRectifyMap 函数生成的 map 应该是目标图像的像素位置到源图像的像素位置的映射,即 dst (x,y)=src(mapx(x,y),mapy(x,y))。见remap在 OpenCV 中。

代码中,ma​​p_1为x方向像素映射,ma​​p_2为y方向像素映射。例如,(X_undistorted, Y_undistorted) 是未失真图像中的像素位置。 ma​​p_1[Y_undistorted, X_undistorted] 告诉你这个像素应该映射到扭曲图像中的 x 坐标,ma​​p_2 会给你相应的 y 坐标。

因此,ma​​p_1ma​​p_2 对于从扭曲的图像构建未扭曲的图像很有用,并不真正适用于逆过程。

remapped_points = []
for corner in corners2:
remapped_points.append(
(map_1[int(corner[0][1]), int(corner[0][0])], map_2[int(corner[0][1]), int(corner[0][0])]))

此代码用于查找角落的未失真像素位置是不正确的。您将需要使用 undistortPoints 函数。


问题 2 的答案:

映射和不失真是不同的。

您可以认为映射是根据未失真图像中的像素位置和像素图构建未失真图像,而未失真是使用镜头失真模型使用原始像素位置找到未失真像素位置。

为了在未失真的图像中找到角点的正确像素位置。您需要使用新估计的 K 将未失真点的归一化坐标转换回像素坐标,在您的情况下,它是 final_K,因为未失真的图像可以看作是由相机拍摄的final_K 没有失真(有一个小的缩放效果)。

这里是修改后的 undistort 函数:

def undistort_list_of_points(point_list, in_K, in_d, in_K_new):
K = np.asarray(in_K)
d = np.asarray(in_d)
# Input can be list of bbox coords, poly coords, etc.
# TODO -- Check if point behind camera?
points_2d = np.asarray(point_list)

points_2d = points_2d[:, 0:2].astype('float32')
points2d_undist = np.empty_like(points_2d)
points_2d = np.expand_dims(points_2d, axis=1)

result = np.squeeze(cv2.fisheye.undistortPoints(points_2d, K, d))

K_new = np.asarray(in_K_new)
fx = K_new[0, 0]
fy = K_new[1, 1]
cx = K_new[0, 2]
cy = K_new[1, 2]

for i, (px, py) in enumerate(result):
points2d_undist[i, 0] = px * fx + cx
points2d_undist[i, 1] = py * fy + cy

return points2d_undist

这是我做同样事情的代码。

import cv2
import numpy as np
import matplotlib.pyplot as plt

K = np.asarray([[556.3834638575809,0,955.3259939726225],[0,556.2366649196925,547.3011305411478],[0,0,1]])
D = np.asarray([[-0.05165940570900624],[0.0031093602070252167],[-0.0034036648250202746],[0.0003390345044343793]])
print("K:\n", K)
print("D:\n", D.ravel())

# read image and get the original image on the left
image_path = "sample.jpg"
image = cv2.imread(image_path)
image = image[:, :image.shape[1]//2, :]
image_gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

fig = plt.figure()
plt.imshow(image_gray, "gray")

H_in, W_in = image_gray.shape
print("Grayscale Image Dimension:\n", (W_in, H_in))

scale_factor = 1.0
balance = 1.0

img_dim_out =(int(W_in*scale_factor), int(H_in*scale_factor))
if scale_factor != 1.0:
K_out = K*scale_factor
K_out[2,2] = 1.0

K_new = cv2.fisheye.estimateNewCameraMatrixForUndistortRectify(K_out, D, img_dim_out, np.eye(3), balance=balance)
print("Newly estimated K:\n", K_new)

map1, map2 = cv2.fisheye.initUndistortRectifyMap(K, D, np.eye(3), K_new, img_dim_out, cv2.CV_32FC1)
print("Rectify Map1 Dimension:\n", map1.shape)
print("Rectify Map2 Dimension:\n", map2.shape)

undistorted_image_gray = cv2.remap(image_gray, map1, map2, interpolation=cv2.INTER_LINEAR, borderMode=cv2.BORDER_CONSTANT)
fig = plt.figure()
plt.imshow(undistorted_image_gray, "gray")

ret, corners = cv2.findChessboardCorners(image_gray, (6,8),cv2.CALIB_CB_ADAPTIVE_THRESH+cv2.CALIB_CB_FAST_CHECK+cv2.CALIB_CB_NORMALIZE_IMAGE)
corners_subpix = cv2.cornerSubPix(image_gray, corners, (3,3), (-1,-1), (cv2.TERM_CRITERIA_EPS + cv2.TERM_CRITERIA_MAX_ITER, 30, 0.1))

undistorted_corners = cv2.fisheye.undistortPoints(corners_subpix, K, D)
undistorted_corners = undistorted_corners.reshape(-1,2)


fx = K_new[0,0]
fy = K_new[1,1]
cx = K_new[0,2]
cy = K_new[1,2]
undistorted_corners_pixel = np.zeros_like(undistorted_corners)

for i, (x, y) in enumerate(undistorted_corners):
px = x*fx + cx
py = y*fy + cy
undistorted_corners_pixel[i,0] = px
undistorted_corners_pixel[i,1] = py

undistorted_image_show = cv2.cvtColor(undistorted_image_gray, cv2.COLOR_GRAY2BGR)
for corner in undistorted_corners_pixel:
image_corners = cv2.circle(np.zeros_like(undistorted_image_show), (int(corner[0]),int(corner[1])), 15, [0, 255, 0], -1)
undistorted_image_show = cv2.add(undistorted_image_show, image_corners)

fig = plt.figure()
plt.imshow(undistorted_image_show, "gray")

关于python - 在 Python 的 OpenCV 中使用鱼眼相机捕获的点不失真的正确方法是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61147903/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com