我正在尝试重新创建一个立体校正算法(不使用任何库(。
我已经用MATLAB校准了一个立体摄像设备。通过MATLAB内置的立体校正算法,我获得了可用的校正图像。
我目前的实现(使用与MATLAB算法相同的校准结果(产生的图像略有偏差(相应的特征没有水平对齐(。为了便于参考,给出了未失真图像的裁剪浮雕。
左图像校正代码:
load('calibration.mat');%load stereoParams
leftImages = imageDatastore('capturesleft');
distortedImage = readimage(leftImages, 1);
kL = stereoParams.CameraParameters1.IntrinsicMatrix';
k1 = stereoParams.CameraParameters1.RadialDistortion(1);
k2 = stereoParams.CameraParameters1.RadialDistortion(2);
translation = stereoParams.TranslationOfCamera2 .* [-1 -1 1]; %translation vector according to initial left camera frame
e1 = translation / norm(translation);
e2 = [-translation(2), translation(1), 0] / norm(translation(1:2));
e3 = cross(e1, e2);
transform = kL * [e1; e2; e3] / kL;
rectifiedImage(1 : 1000, 1 : 1000) = 0;
for r = 1 : 1000
for c = 1 : 1000
undistortedCoord = eye(3) / kL / transform * [c - 1; r - 1; 1]; %map the rectified coordinate to its corresponding unrectified coordinate
undistortedCoord = undistortedCoord / undistortedCoord(3); %normalize unrectified coordinate with respect to its homogeneous component
radius = sqrt(undistortedCoord(1) ^ 2 + undistortedCoord(2) ^ 2); %compute distance from image plane principal point
distortedCoord = [undistortedCoord(1:2) * (1 + k1 * radius ^ 2 + k2 * radius ^ 4); 1]; %compute distorted coordinate from lens distortion coefficients
imageCoord = kL * distortedCoord; %map the distorted coordinate into the distorted image
if (imageCoord(1) > 0 && imageCoord(2) > 0 && imageCoord(1) < size(distortedImage, 2) - 1 && imageCoord(2) < size(distortedImage, 1) - 1)
rectifiedImage(r, c) = double(distortedImage(round(imageCoord(2) + 1), round(imageCoord(1) + 1))) / 255;
end
end
end
imwrite(rectifiedImage, 'rectifiedL.png');
右图像校正代码:
load('calibration.mat');%load stereoParams
rightImages = imageDatastore('capturesright');
distortedImage = readimage(rightImages, 1);
kL = stereoParams.CameraParameters1.IntrinsicMatrix';
kR = stereoParams.CameraParameters2.IntrinsicMatrix';
k1 = stereoParams.CameraParameters2.RadialDistortion(1);
k2 = stereoParams.CameraParameters2.RadialDistortion(2);
translation = stereoParams.TranslationOfCamera2 .* [-1 -1 1]; %translation vector according to initial left camera frame
e1 = translation / norm(translation);
e2 = [-translation(2), translation(1), 0] / norm(translation(1:2));
e3 = cross(e1, e2);
transform = kL * [e1; e2; e3] * stereoParams.RotationOfCamera2 / kR;
rectifiedImage(1 : 1000, 1 : 1000) = 0;
for r = 1 : 1000
for c = 1 : 1000
undistortedCoord = eye(3) / kR / transform * [c - 1; r - 1; 1]; %map the rectified coordinate to its corresponding unrectified coordinate
undistortedCoord = undistortedCoord / undistortedCoord(3); %normalize unrectified coordinate with respect to its homogeneous component
radius = sqrt(undistortedCoord(1) ^ 2 + undistortedCoord(2) ^ 2); %compute distance from image plane principal point
distortedCoord = [undistortedCoord(1:2) * (1 + k1 * radius ^ 2 + k2 * radius ^ 4); 1]; %compute distorted coordinate from lens distortion coefficients
imageCoord = kR * distortedCoord; %map the distorted coordinate into the distorted image
if (imageCoord(1) > 0 && imageCoord(2) > 0 && imageCoord(1) < size(distortedImage, 2) - 1 && imageCoord(2) < size(distortedImage, 1) - 1)
rectifiedImage(r, c) = double(distortedImage(round(imageCoord(2) + 1), round(imageCoord(1) + 1))) / 255;
end
end
end
imwrite(rectifiedImage, 'rectifiedR.png');
除了应用的单应性之外,这些代码块是相同的。
MATLAB的立体校正算法是基于Bouguet算法的,而我的算法是基于略有不同的算法,所以我不希望得到相同的结果,但我相信我应该得到有效的校正图像。
我尝试过许多变体(负平移向量、转置旋转矩阵、不同的输出固有矩阵、不同阶数的矩阵乘法等(,但我无法产生任何有效的结果。根据我使用的算法,我应该颠倒旋转矩阵乘法的顺序,但这样做只会垂直移动右侧图像,从而增加错位。我最初认为图像的比例略有不同,但当在两个图像中使用相同的输出固有矩阵时,这肯定是不可能的。平移矢量已按元素乘以[-1-11],以匹配MATLAB校准工具中显示的左相机坐标系。我尝试过其他变体,如[-1-1-1]、[1 11 1]等,如果某些矩阵被转置,它们可以给出类似的结果,然而,没有一个给出有效的校正。
当我使用MATLAB内部生成的单形图时,我得到了有效的结果,我的单形法出了什么问题?
事实证明,问题是由于平移矢量最初是根据第二个相机坐标系描述的,因此将平移矢量分配更改为
translation = (-stereoParams.RotationOfCamera2 * stereoParams.TranslationOfCamera2')';
导致有效的整改。
事后看来,我早就应该对此进行测试,但如果不是单个组件的迹象,翻译似乎与我在第一台相机坐标系中的预期大致相关。
这非常令人沮丧,因为MATLAB的文档表明,平移已经相对于第一个相机的坐标系进行了。