为iPhone 5创建OpenCV相机矩阵,解决solvepnp问题。

10
我正在使用OpenCV开发一个iPhone应用程序,需要使用solvePnPRansac方法:http://opencv.willowgarage.com/documentation/cpp/camera_calibration_and_3d_reconstruction.html。该方法需要提供一个相机矩阵: __ __
| fx 0 cx |
| 0 fy cy |
|_0 0 1 _|

其中cx和cy表示图像的中心像素位置,fx和fy表示焦距,但文档没有进一步说明。我不确定这些焦距应该提供什么值。iPhone 5的焦距为4.1毫米,但我认为不能直接使用此值。 我查看了另一个网站:http://docs.opencv.org/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html,其中介绍了OpenCV如何创建相机矩阵。这里说明焦距以像素单位测量。
我查看了另一个网站:http://www.velocityreviews.com/forums/t500283-focal-length-in-pixels.html,它说明焦距可以通过公式fx = fy = focalMM * pixelDensity / 25.4; 将毫米转换为像素长度单位。
我对这些方程和如何正确创建此矩阵感到不确定。希望能够获得有关如何创建准确相机矩阵(尤其是iPhone 5)的任何帮助,建议或链接。

艾萨克

p.s. 我认为 (fx/fy) 或 (fy/fx) 可能等于相机的长宽比,但这也可能是完全错误的。

更新:

像素坐标转 3D 线 (opencv)

使用此链接,我可以弄清楚他们希望如何格式化 fx 和 fy,因为他们用它来缩放与中心的距离相关的角度。因此,fx 和 fy 可能以像素/(单位长度) 的形式存在,但我仍然不确定这个单位长度需要是多少,是否可以任意设置,只要 x 和 y 相对缩放即可?

5个回答

10

通过将相机镜头焦距(以毫米为单位)除以相机传感器的像素宽度(CCD、CMOS等),可以获得焦距在像素中的初始(粗略)估计。

您可以从相机手册中获取前者,或从拍摄全分辨率图像的EXIF标头中读取。找出后者要复杂一些:如果您知道制造商和型号号码,可以查询传感器规格表,或者仅将其灵敏区域的总宽度除以侧面上的像素数。

如果没有其他信息,通常可以安全地假设像素是正方形的(即fx == fy),并且传感器垂直于镜头的焦轴(即相机矩阵第一行和第二列的术语为零)。此外,主点(cx,cy)的像素坐标通常很难准确估计,除非使用精心设计的校准装置和谨慎执行的校准程序(这是因为它们与平行于图像平面的相机平移本质上混淆)。因此,最好将它们设置为图像的几何中心,除非您知道图像已被不对称地裁剪。

因此,您的最简单的相机模型只有一个未知参数,即焦距f = fx = fy。

建议:在您的应用程序中,通常更方便携带水平(或垂直)视场角,而不是像素焦距。这是因为FOV对图像缩放不变。


谢谢您的回复,我觉得很有帮助并且信息量大。只有一个小问题:根据视野角度,我在网上找到了fy = fx = cx /(tan((水平角度)/ 2))这个公式,这是您推荐的公式吗? - Isaac
还有,如果我按照这种方式构建我的fx,我是否仍然可以以这种方式获得相对于我的相机的向量:https://dev59.com/tk7Sa4cB1Zd3GeqP5KOk?rq=1 - Isaac
点赞指出FoV是有利的参数,因为它是独立于比例的。 - hAcKnRoCk

6
你所处理的“焦距”只是物体与相机像素之间的比例因子,在针孔相机模型(维基百科链接)中使用。这就是为什么它的单位是像素/单位长度。对于给定的f,在距离(垂直于相机)z处大小为L的对象将成为f * L / z像素。
所以,您可以通过在已知距离下放置已知尺寸的物体并测量其在图像中的大小来估算焦距。您也可以假设中心点是图像的中心。您一定不应忽略镜头畸变 (solvePnPRansac中的dist_coef参数)。
实际上,获得相机内参矩阵和畸变系数的最佳方法是使用相机校准工具。您可以从此链接下载并使用MRPT camera_calib 软件,该软件还有视频教程。如果您使用Matlab,则可以使用Camera Calibration Toolbox

谢谢您的回答,我想我会简单地用 iPhone 5 相机录制棋盘,并使用您发送的第二个链接。您认为是否有适用于 iPhone 5 的预制相机矩阵和畸变系数? - Isaac
3
@Isaac:我不知道有没有iPhone 5的预制相机矩阵,但你可以发布你的校准结果;-) - Milo

4

这里有一张表格,列出了iPhone 4和5相机的规格。 计算方法如下:

double f = 4.1;
double resX = (double)(sourceImage.cols);
double resY = (double)(sourceImage.rows);
double sensorSizeX = 4.89;
double sensorSizeY = 3.67;
double fx = f * resX / sensorSizeX;
double fy = f * resY / sensorSizeY;
double cx = resX/2.;
double cy = resY/2.;

1

旧帖,现在的问题。

正如Milo和Isaac在Milo的回答之后提到的那样,似乎没有适用于iPhone 5等设备的“通用”参数。

值得一提的是,这是使用MRPT校准工具对一个老旧的iPhone 5进行测试的结果:

[CAMERA_PARAMS]
resolution=[3264 2448]
cx=1668.87585
cy=1226.19712
fx=3288.47697
fy=3078.59787
dist=[-7.416752e-02 1.562157e+00 1.236471e-03 1.237955e-03 -5.378571e+00]

Average err. of reprojection: 1.06726 pixels (OpenCV error=1.06726)

请注意,这里的dist表示畸变。
我正在进行一个玩具项目的实验,使用这些参数——还算可以。如果您将它们用于自己的项目,请记住它们可能不足以开始。最好的方法是按照Milo的建议使用自己的数据。MRPT工具非常易于使用,配合他们提供的棋盘格即可。希望这能帮助您入门!

1

试试这个:

func getCamMatrix()->(Float, Float, Float, Float)
{

    let format:AVCaptureDeviceFormat? = deviceInput?.device.activeFormat
    let fDesc:CMFormatDescriptionRef = format!.formatDescription

    let dim:CGSize = CMVideoFormatDescriptionGetPresentationDimensions(fDesc, true, true)

    // dim = dimensioni immagine finale
    let cx:Float = Float(dim.width) / 2.0;
    let cy:Float = Float(dim.height) / 2.0;

    let HFOV : Float = format!.videoFieldOfView
    let VFOV : Float = ((HFOV)/cx)*cy

    let fx:Float = abs(Float(dim.width) / (2 * tan(HFOV / 180 * Float(M_PI) / 2)));
    let fy:Float = abs(Float(dim.height) / (2 * tan(VFOV / 180 * Float(M_PI) / 2)));

    return (fx, fy, cx, cy)
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接