我已经使用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
GoPro规范
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 ]
用于校准的图像之一
和不失真的图像
最佳答案
您已经在OpenCV中输入了6.17
mm和4.55
mm作为传感器尺寸,这对应于纵横比1.36
,而分辨率(1270x720)为1.76
(大约16x9格式)。
您是否在MATLAB校准之前裁剪了图像?
像素大小似乎比this Gopro page为1.55µm(这真是太小了!)。如果像素是平方的,并且应该在这种类型的商用相机上,则意味着您的输入不连贯。计算的传感器大小应为:
即使考虑最大视频分辨率为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]
(水平,垂直方向为idem)。然后,将opencv.core.Size(1280, 720)
替换为获得的最极端范围,您有望检索Gopro网站值。
总而言之,我认为如果在图像中心进行测量,则可以依靠获得的焦距值,否则失真太大,因此不适用。
关于opencv - GoPro摄像机的视场,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/40023288/