opencv立体声矫正失败,但我认为立体声校准成功

时间:2018-07-31 21:00:09

标签: opencv computer-vision camera-calibration stereo-3d

我有一组类似的校准图像,从中我获得了左侧图像中的图像点(棋盘角位置),“ imp1”,右侧图像中的图像点,“ imp2”和世界框架中的对象点。 ,'objp'。一系列图像中的棋盘位置至少占据了场景的80%。会仔细拍摄它们,并同时从高质量的科学相机中拍摄快照。唯一的麻烦是它们在水下,因此会有灯光波动和可能很小的振动。

enter image description here

首先,我分别使用cv2.calibrateCamera对每个视图进行了摄像机校准。我获得约0.3像素的重投影误差。显然失真很小。使用cv2.undistort使图像不失真会导致直线看起来直的图像。当然,直线在原始图像中也看起来是直线。相机校准代码为

flags = cv2.CALIB_FIX_PRINCIPAL_POINT | cv2.CALIB_FIX_K3 | cv2.CALIB_ZERO_TANGENT_DIST

cam1 = cv2.calibrateCamera(objp,imp1,shape,None,None,flags=flags)
cam2 = cv2.calibrateCamera(objp,imp2,shape,None,None,flags=flags)

# store the output 
keys = ['retval','cameraMatrix','distCoeffs','rvecs','tvecs']
Lcam = {k:v for k,v in zip(keys,cam1)}
Rcam = {k:v for k,v in zip(keys,cam2)}

第二,我使用cv2.stereoCalibrate进行了立体校准,如下所示

# do the stereo calibration
flags =  cv2.CALIB_USE_INTRINSIC_GUESS | cv2.CALIB_FIX_FOCAL_LENGTH | cv2.CALIB_FIX_PRINCIPAL_POINT | cv2.CALIB_FIX_INTRINSIC | cv2.CALIB_FIX_K1 | cv2.CALIB_FIX_K2 | cv2.CALIB_FIX_K3 
stereocalib = cv2.stereoCalibrate(objp,imp1,imp2,Lcam['cameraMatrix'],Lcam['distCoeffs'],Rcam['cameraMatrix'],Rcam['distCoeffs'],shape,flags=flags)

#store the output
keys = ['retval', 'cameraMatrix1', 'distCoeffs1', 'cameraMatrix2', 'distCoeffs2', 'R', 'T', 'E', 'F']
stereo = {k:v for k,v in zip(keys,stereocalib)}

这将获得重投影误差0.8,并且当我计算对极约束x'Fx的偏差时,对于所有成对的点x和x',我发现它们始终小于1个像素,通常更像0.2个像素。

在下图中,左侧图像中指示了三个棋盘角点,右侧图像中指示了它们对应的外延线。 enter image description here

这两个测试,对极约束残差计算和相应的Epiline可视化使我对立体校准结果充满信心。

我的第一个问题出现在这里:我不知道如何测试旋转和平移矩阵。所获得的转换矩阵(即,立体声['T'])为

array([[-94.35664281],
   [  1.45841307],
   [  6.63416548]])

获得的旋转矢量(即,立体声['R'])为

array([[ 8.42562933e-01,  1.53811356e-02,  5.38378236e-01],
   [-1.31180579e-02,  9.99881661e-01, -8.03622020e-03],
   [-5.38438131e-01, -2.91455620e-04,  8.42664995e-01]])

离身份不远。在我看来,这似乎是围绕y轴的一个小旋转,这是有道理的,因为相机略微相互倾斜。

这里的单位是厘米。摄像头的安装点(略微位于镜头的上方和后面)彼此间隔约100cm,因此这似乎很合理。一个相机机身比另一个相机机身长,可能长约6厘米。一个坐骑比另一个坐骑低一点,可能约2cm。我对x坐标上的负号感到困惑。如何测试旋转和平移矩阵?

第三,现在进入第二个问题,我尝试从cv2.stereoRectify生成用于立体校正的投影矩阵,如下所示:

alpha = 1
rect = cv2.stereoRectify(stereo['cameraMatrix1'],stereo['distCoeffs1'],stereo['cameraMatrix2'],stereo['distCoeffs2'],shape,stereo['R'],stereo['T'],alpha,flags=cv2.CALIB_ZERO_DISPARITY)

# store the rectification parameters
keys = ['R1','R2','P1','P2','Q','validPixROI1','validPixROI2'] 
rectify = {k:v for k,v in zip(keys,rect)}

然后我将重投影图计算为

lmaps = cv2.initUndistortRectifyMap(stereo["cameraMatrix1"], stereo["distCoeffs1"], rectify['R1'], rectify['P1'], shape, cv2.CV_16SC2)
rmaps = cv2.initUndistortRectifyMap(stereo["cameraMatrix2"], stereo["distCoeffs2"], rectify['R2'], rectify['P2'], shape, cv2.CV_16SC2)

我将左图中的每个图像“ l”重新映射为

interpolate = cv2.INTER_LANCZOS4 
lr = cv2.remap(l, lmaps[0], lmaps[1], interpolate)

,右视图中的每个图像'r'均为

 rr = cv2.remap(r, rmaps[0], rmaps[1], interpolate)

结果是:

from matplotlib import pyplot as plt
plt.imshow(np.hstack((lr,rr)))
plt.show()

enter image description here

这适用于所有alpha值。重投影图具有负值,并且这些值不位于图像上,因此校正会产生废话。

我有两个问题

首先,如何测试cv2.stereoCalibrate产生的旋转矩阵和平移矢量?

第二,有人对我有什么建议,可以对场景的两种视图进行有益的纠正?

目标是根据摄像机视图中配对的对象观测值对对象的3D世界位置进行三角剖分。纠正是前提条件。任何帮助表示赞赏!我会尽力澄清所有不清楚的地方。

0 个答案:

没有答案