在 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_32F
和 CV_64F
。
更新
我不知道 Java,但在 C++ 中,当你创建一个 Mat
时,它的初始值是未指定的,所以这段代码可能正在创建一个矩阵 [=第一项为 20=],其余项为垃圾:
Mat distCoefficientMatrix = new Mat(1, 4, CvType.CV_32F);
distCoefficientMatrix.put(0, 0, 2f);
你能检查一下这是否是问题所在吗?
未来的注意事项,为了让事情变得更棘手,请考虑到 OpenCV 中的固有校准矩阵是 Matlab 中的矩阵的转置。
我有一个 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_32F
和 CV_64F
。
更新
我不知道 Java,但在 C++ 中,当你创建一个 Mat
时,它的初始值是未指定的,所以这段代码可能正在创建一个矩阵 [=第一项为 20=],其余项为垃圾:
Mat distCoefficientMatrix = new Mat(1, 4, CvType.CV_32F);
distCoefficientMatrix.put(0, 0, 2f);
你能检查一下这是否是问题所在吗?
未来的注意事项,为了让事情变得更棘手,请考虑到 OpenCV 中的固有校准矩阵是 Matlab 中的矩阵的转置。