确定智能手机相机的视角

Gob*_*ffi 19 math camera android angle

我正在尝试确定Droid Incredible智能手机相机的视野的大小.我需要知道我正在开发的应用程序的这个值.有谁知道如何以编程方式找出/计算它?

Dor*_*rje 58

Camera.Parameters getHorizo​​ntalViewAngle()和getVerticalViewAngle()函数为您提供基本视角.我说"base",因为它们仅适用于处于unzoomed状态的Camera本身,并且这些函数返回的值即使在视角本身的情况下也不会改变.

Camera.Parameters p = camera.getParameters();
double thetaV = Math.toRadians(p.getVerticalViewAngle());
double thetaH = Math.toRadians(p.getHorizontalViewAngle());
Run Code Online (Sandbox Code Playgroud)

有两个因素会导致您的"有效"视角发生变化:缩放,并使用与相机宽高比不匹配的预览宽高比.

基础数学

视场(Θ)的三角学非常简单:

tan(Θ/ 2)= x/2z

x = 2z tan(Θ/ 2)

x是距离z处可见的线性距离; 也就是说,如果你在距离z = 1米处举起一把尺子,你就可以看到那个尺子的x米.

例如,在我的相机上,水平视野为52.68°,而垂直视野为40.74°.将它们转换为弧度并将它们插入到具有任意z值100m的公式中,并获得99.0m(水平)和74.2m(垂直)的x值.这是4:3的宽高比.

放大

将此数学应用于缩放级别只是稍微困难一些.现在,x保持不变,并且z以已知比率变化; 我们必须确定Θ.

tan(Θ/ 2)= x /(2z)

tan(Θ'/ 2)= x /(2z')

Θ'= 2 atan((z/z')tan(Θ/ 2))

其中z是基本缩放级别(100),z'是当前缩放级别(来自CameraParameters.getZoomRatios),Θ是基本水平/垂直视野,Θ'是有效视野.添加度数 - >弧度转换使得这相当冗长.

private static double zoomAngle(double degrees, int zoom) {
    double theta = Math.toRadians(degrees);
    return 2d * Math.atan(100d * Math.tan(theta / 2d) / zoom);
}

Camera.Parameters p = camera.getParameters();
int zoom = p.getZoomRatios().get(p.getZoom()).intValue();
double thetaH = zoomAngle(p.getHorizontalViewAngle(), zoom);
double thetaV = zoomAngle(p.getVerticalViewAngle(), zoom);
Run Code Online (Sandbox Code Playgroud)

宽高比

虽然典型的相机是4:3的宽高比,但预览也可以5:3和16:9的比例提供,这似乎是通过实际扩展水平视场来实现的.这似乎是无证的,因此不可靠,但通过假设它是如何工作的,我们可以计算视野.

数学类似于缩放计算; 但是,在这种情况下,z保持不变,而x则会发生变化.通过假设垂直视角保持不变而水平视角随宽高比变化而变化,可以计算新的有效水平视角.

tan(Θ/ 2)= v /(2z)

tan(Θ'/ 2)= h /(2z)

2z = v/tan(Θ/ 2)

Θ'= 2 atan((h/v)tan(Θ/ 2))

这里h/v是纵横比,Θ是基本垂直视场,而Θ'是有效的水平视场.

Camera.Parameters p = camera.getParameters();
int zoom = p.getZoomRatios().get(p.getZoom()).intValue();
Camera.Size sz = p.getPreviewSize();
double aspect = (double) sz.width / (double) sz.height;
double thetaV = Math.toRadians(p.getVerticalViewAngle());
double thetaH = 2d * Math.atan(aspect * Math.tan(thetaV / 2));
thetaV = 2d * Math.atan(100d * Math.tan(thetaV / 2d) / zoom);
thetaH = 2d * Math.atan(100d * Math.tan(thetaH / 2d) / zoom);
Run Code Online (Sandbox Code Playgroud)

正如我上面所说,由于这似乎没有记录,只是猜测它将适用于所有设备; 它应该被认为是一个黑客.正确的解决方案是拆分一组新函数getCurrentHorizo​​ntalViewAngle和getCurrentVerticalViewAngle.

  • getHorizo​​ntalViewAngle()和getVerticalViewAngle()结果可以为各种设备提供信任吗? (3认同)
  • 是否有类似的方法(相机2 API中的getVertical/Horizo​​ntalViewingAngle()?我没有看到它们,并且想知道我是否错过了它们,或者它们是否不存在.可能在CameraCharacteristics中? (2认同)

Dav*_*d Z 14

除非有一些API调用(我不是Android程序员,我不知道),我只是从已知距离拍摄一张标尺的图片,看看图片中显示了多少标尺,然后用三角找到喜欢的角度这样:

在此输入图像描述

现在你从图中得到两个距离l和d.通过一些简单的测角仪,人们可以获得:

tan(α/ 2)=(l/2)/ d,

于是

α= 2*atan(l/2d)

因此,使用此公式,您可以计算相机的水平视野.当然,测量垂直fov的方式完全相同,只是您需要在垂直位置查看对象.

然后,您可以将其硬编码为程序中的常量.(当然,这是一个命名常数,因此很容易改变:-p)


Max*_*Max 9

我也有一个Droid Incredible.Android 2.2引入了您正在寻找的功能.在我的代码中,我有:

public double getHVA() {
    return camera.getParameters().getHorizontalViewAngle();
}

public double getVVA() {
    return camera.getParameters().getVerticalViewAngle();
}
Run Code Online (Sandbox Code Playgroud)

但是,这些要求您打开相机.我有兴趣知道是否有一种"最佳实践"的方式,每次都不需要打开相机来获得这些值.

@David Zaslavsky - 怎么样?缩放级别之间的数学关系是什么?我无法在任何地方找到它(我在这个问题中提到:Android相机缩放数字在数学上代表什么?)