我使用用于Matlab的相机校准工具箱校准了我的GoPro Hero 4 Black,并使用 OpenCV 计算了它的视野和焦距范围calibrationMatrixValues()的。但是,这些与GoPro的规格不同。相当于118.2 / 69.5 FOV,我得到95.4 / 63.4,焦距2.8mm而不是17.2mm。显然有些不对劲。
我认为校准本身是正确的,因为图像失真似乎运作良好。
任何人都可以在我犯错的地方给我一个提示吗?我在下面发布我的代码。
感谢。
cameraMatrix = new Mat(3, 3, 6);
for (int i = 0; i < cameraMatrix.height(); i ++)
for (int j = 0; j < cameraMatrix.width(); j ++) {
cameraMatrix.put(i, j, 0);
}
cameraMatrix.put(0, 0, 582.18394);
cameraMatrix.put(0, 2, 663.50655);
cameraMatrix.put(1, 1, 582.52915);
cameraMatrix.put(1, 2, 378.74541);
cameraMatrix.put(2, 2, 1.);
org.opencv.core.Size size = new org.opencv.core.Size(1280, 720);
//output parameters
double [] fovx = new double[1];
double [] fovy = new double[1];
double [] focLen = new double[1];
double [] aspectRatio = new double[1];
Point ppov = new Point(0, 0);
org.opencv.calib3d.Calib3d.calibrationMatrixValues(cameraMatrix, size,
6.17, 4.55, fovx, fovy, focLen, ppov, aspectRatio);
System.out.println("FoVx: " + fovx[0]);
System.out.println("FoVy: " + fovy[0]);
System.out.println("Focal length: " + focLen[0]);
System.out.println("Principal point of view; x: " + ppov.x + ", y: " + ppov.y);
System.out.println("Aspect ratio: " + aspectRatio[0]);
FoVx: 95.41677635378488
FoVy: 63.43170132212425
Focal length: 2.8063085232812504
Principal point of view; x: 3.198308916796875, y: 2.3934605770833333
Aspect ratio: 1.0005929569269807
https://gopro.com/help/articles/Question_Answer/HERO4-Field-of-View-FOV-Information
Matlab校准结果
Focal Length: fc = [ 582.18394 582.52915 ] ± [ 0.77471 0.78080 ]
Principal point: cc = [ 663.50655 378.74541 ] ± [ 1.40781 1.13965 ]
Skew: alpha_c = [ -0.00028 ] ± [ 0.00056 ] => angle of pixel axes = 90.01599 ± 0.03208 degrees
Distortion: kc = [ -0.25722 0.09022 -0.00060 0.00009 -0.01662 ] ± [ 0.00228 0.00276 0.00020 0.00018 0.00098 ]
Pixel error: err = [ 0.30001 0.28188 ]
答案 0 :(得分:4)
您已在OpenCV中输入6.17
mm和4.55
mm作为传感器尺寸,这对应于宽高比1.36
,而您的分辨率(1270x720)为1.76
(大约16x9格式)。
您是否在MATLAB校准之前裁剪图像?
this Gopro page的像素大小似乎是1.55μm(这是非常小的方式!)。如果像素是平方的,并且它们应该在这种类型的商业相机上,这意味着您的输入不连贯。计算的传感器尺寸应为:
[传感器宽度,传感器高度] = [1280,720] * 1.55 * 10 ^ -3 = [1.97,1.12] 毫米
即使考虑到最大视频分辨率为3840 x 2160,我们也会获得[5.95, 3.35]mm
,但仍与您的输入不同。
请参阅此explanation about equivalent focal length以了解为什么相机的实际焦距不 17.2
但17.2*5.95/36
~2.8mm。在这种情况下,例如使用公式here计算FOV。您确实会发现93.5°/ 61.7°的值(接近您的输出,但仍然没有在规范中写入,因为广角可能会出现一些光学失真)。
我不明白的是,返回的焦距是如何正确的,而输入的传感器尺寸是错误的。你能提供更多信息和/或发送图片吗?
问题更新后进行修改
在相机上,工作分辨率为1280x720,图像被下采样但没有裁剪,所以我上面所说的传感器尺寸不适用。要考虑的传感器尺寸确实是您使用的尺寸(6.17x4.55),如您的第一条评论所述。
FOV受到以像素和分辨率给出的校准矩阵输入(fx,fy,cx,cy)的约束。您可以输入以下内容进行检查:
2*DEGRES(ATAN(1280/(2*582.18394)))
(= 95.416776 ...°)
此FOV值小于预期值,但通过未失真图像的外观,您的MATLAB失真模型是正确的,校准是正确的。由于广角引起的桶形失真似乎可以通过您应用的重复修正得到很好的修正。
然而,MATLAB工具箱使用针孔模型,该模型是线性的,无法解释内在参数,如镜头失真。我在页面上假设这一点:
https://fr.mathworks.com/help/vision/ug/camera-calibration.html
因此,我最好的猜测是,除非你找到一个更准确地适合Gopro相机的模型(可能是广角镜头模型),否则MATLAB校准将返回与“线性”无失真图像相对应的内在相机矩阵。 FOV确实会更小(在桶形失真的情况下)。您必须应用与校准相关的失真系数来检索实际的FOV值。
我们可以在校正的图像中看到FOV的侧面部分被拒绝超出范围。如果你完全扭曲了图像,你会发现一些未失真的像素坐标超过[-1280/2;+1280/2]
(水平,垂直同构)。然后,将opencv.core.Size(1280, 720)
替换为获得的最极端范围,您可能希望检索Gopro网站值。
总而言之,我认为如果你在图像的中心进行测量,你可以依赖你获得的焦距值,否则失真太多而且不适用。