我正在尝试重新创建立体声整流算法(不使用任何库)。
我已经使用MATLAB校准了立体相机装置。使用MATLAB的内置立体声校正算法,可以获得可用的校正图像。
我当前的实现(使用与MATLAB算法相同的校准结果)所产生的图像略有偏移(相应的要素未水平对齐)。作为参考,给出了未失真图像的裁剪立体图。
纠正左侧图像的代码:
load('calibration.mat');%load stereoParams
leftImages = imageDatastore('captures\left\');
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('captures\right\');
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 -1 1]以匹配在MATLAB的校准工具中显示的左侧相机坐标系。我尝试了其他变体,例如[-1 -1 -1],[1 1 1]等。
当我使用MATLAB内部生成的单应字时,我得到了有效的结果,我的单应字怎么了?
事实证明,此问题是由以下事实引起的:平移向量最初是根据第二个摄像机坐标系描述的,因此将平移向量分配更改为
translation = (-stereoParams.RotationOfCamera2 * stereoParams.TranslationOfCamera2')';
导致有效的纠正。
事后看来,我早就应该对此进行测试了,但是翻译似乎与我在第一台摄像机的坐标系中所期望的大致相关,即使不是针对各个组件的符号。
这非常令人沮丧,因为MATLAB的文档表明,已经相对于第一个摄像机的坐标系进行了平移。