我有一对水平对齐的立体相机,它们是使用图像的全尺寸进行校准的。
我通过调用 cv2.initUn DistreifyMap 来获取每个相机的地图来进行纠正,然后调用 cv2.remap
使用全尺寸图像时,看起来像:
map1, map2 = cv2.initUndistortRectifyMap(camera_matrix_1, dist_coeffs_1, R1, P1, (w, h), cv2.CV_16SC2)
map3, map4 = cv2.initUndistortRectifyMap(camera_matrix_2, dist_coeffs_2, R2, P2, (w, h), cv2.CV_16SC2)
rectified1 = cv2.remap(img1, map1, map2, cv2.INTER_LINEAR)
rectified2 = cv2.remap(img2, map3, map4, cv2.INTER_LINEAR)
其中
cv2.initUndistortRectifyMap
的参数是 cv2.stereoCalibrate
和 cv2.stereoRectify
的输出
但是,为了提高处理速度,图像在处理时将被裁剪(并可能被合并),然后才能进行校正。这意味着校正过程无法使用图像的完整尺寸。
在完成校正之前,需要更改哪些内容才能使代码能够用于图像的裁剪(和合并)?
如果您想对原始
img1
和img2
进行裁剪和调整大小(缩放)并在校准后使用它,那么您需要更改camera_matrix_1
和camera_matrix_2
。裁剪改变了一个主点,比例改变了焦距。但rectified1
和rectified2
的结果(输出)不会改变它的大小:w, h
。如果您想要更小的输出图像,您需要更改 P1
和 P2
。
z 0 sx
0 z sy * camera_matrix -> camera_matrix'
0 0 1
分别是
z
- 比例因子,s
- 裁剪图像中心的移动。 camera_matrix
和 P
的比例和移位可能不同。
不要忘记使用 map1
和新参数重新创建 map2
、initUndistortRectifyMap
...。
要消除黑色区域,请使用以下代码根据有效的 ROI 裁剪校正图像。
R1, R2, P1, P2, Q, validRoi1, validRoi2 = cv2.stereoRectify(Kl, Dl, Kr, Dr, image_size, R, T, flags=cv2.CALIB_ZERO_DISPARITY, alpha=1)
xl, yl, wl, hl = validRoi1
xr, yr, wr, hr = validRoi2
x = max(xl, xr)
w = min(wl, wr)
y = max(yl, yr)
h_ind = np.argmin([yl+hl, yr+hr])
if h_ind == 0:
h = hl
else:
h = hr - y
xmap1, ymap1 = cv2.initUndistortRectifyMap(Kl, Dl, R1, P1, image_size, cv2.CV_32FC1)
xmap2, ymap2 = cv2.initUndistortRectifyMap(Kr, Dr, R2, P2, image_size, cv2.CV_32FC1)
left_img_rectifiedt = cv2.remap(left_img, xmap1, ymap1, cv2.INTER_LINEAR)
right_img_rectifiedt = cv2.remap(right_img, xmap2, ymap2, cv2.INTER_LINEAR)
left_img_rectified = cv2.remap(left_img, xmap1, ymap1, cv2.INTER_LINEAR)[y:y+h, xl:xl+w]
right_img_rectified = cv2.remap(right_img, xmap2, ymap2, cv2.INTER_LINEAR)[y:y+h, xr:xr+w]