Warm tip: This article is reproduced from serverfault.com, please click

matlab-立体声整流如何实施?

(matlab - How is stereo rectification implemented?)

发布于 2020-11-28 11:35:29

我正在尝试重新创建立体声整流算法(不使用任何库)。

我已经使用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内部生成的单应字时,我得到了有效的结果,我的单应字怎么了?

Questioner
mill6aqer
Viewed
11
mill6aqer 2020-11-30 15:34:28

事实证明,此问题是由以下事实引起的:平移向量最初是根据第二个摄像机坐标系描述的,因此将平移向量分配更改为

translation = (-stereoParams.RotationOfCamera2 * stereoParams.TranslationOfCamera2')';

导致有效的纠正。

事后看来,我早就应该对此进行测试了,但是翻译似乎与我在第一台摄像机的坐标系中所期望的大致相关,即使不是针对各个组件的符号。

这非常令人沮丧,因为MATLAB的文档表明,已经相对于第一个摄像机的坐标系进行了平移。