在 OpenCV 程序中使用 MATLAB cameraParams

Use MATLAB cameraParams in OpenCV program

我有一个 MATLAB 程序可以加载两个图像和 returns 两个相机矩阵和一个带有畸变系数的 cameraParams 对象等。我现在想使用这个精确的配置来消除畸变点等等,在一个 OpenCV 程序,根据两个不同视频中的 2D 位置对点进行三角测量。

function [cameraMatrix1, cameraMatrix2, cameraParams] = setupCameraCalibration(leftImageFile, rightImageFile, squareSize)
% Auto-generated by cameraCalibrator app on 20-Feb-2015

事实是,undistortPoints 的输出在 MATLAB 和 OpenCV 中是不同的,即使它们使用相同的参数。

举个例子:

>> undistortPoints([485, 502], defaultCameraParams)
ans = 485   502

在Java中,下面的测试模拟了上面的测试(它通过了)。

public void testUnDistortPoints() {
    Mat srcMat = new Mat(2, 1, CvType.CV_32FC2);
    Mat dstMat = new Mat(2, 1, CvType.CV_32FC2);
    srcMat.put(0, 0, new float[] { 485, 502 } );

    MatOfPoint2f src = new MatOfPoint2f(srcMat);
    MatOfPoint2f dst = new MatOfPoint2f(dstMat);

    Mat defaultCameraMatrix = Mat.eye(3, 3, CvType.CV_32F);
    Mat defaultDistCoefficientMatrix = new Mat(1, 4, CvType.CV_32F);

    Imgproc.undistortPoints(
            src,
            dst,
            defaultCameraMatrix,
            defaultDistCoefficientMatrix
    );

    System.out.println(dst.dump());

    assertEquals(dst.get(0, 0)[0], 485d);
    assertEquals(dst.get(0, 0)[1], 502d);
}

但是,假设我改变了第一个失真系数(k1)。在 MATLAB 中:

changedDist = cameraParameters('RadialDistortion', [2 0 0])
>> undistortPoints([485, 502], changedDist)
ans = 4.8756    5.0465

在Java中:

public void testUnDistortPointsChangedDistortion() {
    Mat srcMat = new Mat(2, 1, CvType.CV_32FC2);
    Mat dstMat = new Mat(2, 1, CvType.CV_32FC2);
    srcMat.put(0, 0, new float[] { 485, 502 } );

    MatOfPoint2f src = new MatOfPoint2f(srcMat);
    MatOfPoint2f dst = new MatOfPoint2f(dstMat);

    Mat defaultCameraMatrix = Mat.eye(3, 3, CvType.CV_32F);
    Mat distCoefficientMatrix = new Mat(1, 4, CvType.CV_32F);
    distCoefficientMatrix.put(0, 0, 2f); // updated

    Imgproc.undistortPoints(
            src,
            dst,
            defaultCameraMatrix,
            distCoefficientMatrix
    );

    System.out.println(dst.dump());

    assertEquals(4.8756, dst.get(0, 0)[0]);
    assertEquals(5.0465, dst.get(0, 0)[1]);
}

失败并输出以下内容:

[0.0004977131, 0.0005151587]

junit.framework.AssertionFailedError: 
Expected :4.8756
Actual   :4.977131029590964E-4

为什么结果不同?我以为Java的畸变系数矩阵包括了径向畸变系数和切向畸变系数

此外,CV_64FC1 是相机/畸变系数矩阵类型的不错选择吗?

我想测试改变相机矩阵本身的效果(即f_x的值),但是使用cameraparams时无法设置'IntrinsicMatrix'参数,所以我想先解决畸变矩阵问题

如有任何帮助,我们将不胜感激。

在使用校准模型时,您必须考虑几件事。

首先,请注意存在几种相机校准和失真模型:Tsai, ATAN, Pinhole, Ocam. I assume you want to use the Pinhole model, which is the used by OpenCV and the most common one. It models from 2 to 6 parameters for radial distortion (denoted as k1...k6) and 2 for tangential distortion (denoted as p1, p2), as you can read in the OpenCV doc. Bouget's calibration toolbox for Matlab 也使用此模型。

其次,没有一种标准化的方式来排列向量中的失真参数。 OpenCV 需要以下顺序的项目:[k1 k2 p1 p2 k3...k6]k3...k6 可选。

因此,请检查您的 Matlab 校准软件的文档,并查找它使用的模型以及参数的排列顺序。然后,确保它符合OpenCV中的顺序。

我记得 OpenCV 的校准参数是 CV_32FCV_64F

更新

我不知道 Java,但在 C++ 中,当你创建一个 Mat 时,它的初始值是未指定的,所以这段代码可能正在创建一个矩阵 [=第一项为 20=],其余项为垃圾:

Mat distCoefficientMatrix = new Mat(1, 4, CvType.CV_32F);
distCoefficientMatrix.put(0, 0, 2f);

你能检查一下这是否是问题所在吗?

未来的注意事项,为了让事情变得更棘手,请考虑到 OpenCV 中的固有校准矩阵是 Matlab 中的矩阵的转置。