确定智能手机相机的视角

时间:2010-07-16 03:41:01

标签: android math camera angle

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

3 个答案:

答案 0 :(得分: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());

两件事导致您的“有效”视角发生变化:缩放,并使用与相机宽高比不匹配的预览宽高比。

基础数学

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

  

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);

宽高比

虽然典型相机的宽高比为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);

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

答案 1 :(得分:13)

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

enter image description here

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

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

因此

α= 2 * atan(l / 2d)

因此,使用此公式,您可以计算相机的水平视野。当然测量垂直f.o.v.除了你需要在垂直位置查看对象之外,它的方式完全相同。

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

答案 2 :(得分:9)

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

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

public double getVVA() {
    return camera.getParameters().getVerticalViewAngle();
}

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

@David Zaslavsky - 怎么样?缩放级别之间的数学关系是什么?我无法在任何地方找到它(我在这个问题中提到:What do the Android camera zoom numbers mathematically represent?