Android 确定智能手机相机的视角
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3261776/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Determine angle of view of smartphone camera
提问by GobiasKoffi
I'm trying to determine the degree size of the field-of-view of a Droid Incredible smartphone's camera. I need to know this value for an application that I'm developing. Does anyone know how I can find out/calculate it programmatically?
我正在尝试确定 Droid Incredible 智能手机相机视场的度数大小。我需要知道我正在开发的应用程序的这个值。有谁知道我如何以编程方式找出/计算它?
采纳答案by David Z
Unless there's some API call for that (I'm not an Android programmer, I wouldn't know), I would just snap a picture of a ruler from a known distance away, see how much of the ruler is shown in the picture, then use trigonometry to find the angle like this:
除非有一些 API 调用(我不是 Android 程序员,我不知道),否则我只会从已知距离拍一张尺子的照片,看看图中显示了多少尺子,然后用三角找到喜欢的角度这样:
now you have the two distances l and d from the figure. With some simple goniometry, one can obtain:
现在你有两个距离 l 和 d 的数字。通过一些简单的测角,可以得到:
tan(α/2) = (l/2)/d,
tan(α/2) = (l/2)/d,
hence
因此
α = 2*atan(l/2d)
α = 2*atan(l/2d)
So with this formula you can calculate the horizontal field-of-view of your camera. Of course measuring the vertical f.o.v. goes exactly the same way except that you then need to view the object in its vertical position.
因此,使用此公式,您可以计算相机的水平视场。当然,测量垂直 fov 的方式完全相同,只是您需要在其垂直位置查看对象。
Then you can hard-code it as a constant in your program. (A named constant, of course, so it'd be easy to change :-p)
然后您可以将其硬编码为程序中的常量。(当然,一个命名常量,所以很容易改变:-p)
回答by Dorje
The Camera.Parameters getHorizontalViewAngle() and getVerticalViewAngle() functions provide you with the base view angles. I say "base", because these apply only to the Camera itself in an unzoomed state, and the values returned by these functions do not change even when the view angle itself does.
Camera.Parameters getHorizontalViewAngle() 和 getVerticalViewAngle() 函数为您提供基本视角。我说“基础”,因为这些仅适用于未缩放状态的相机本身,并且即使视角本身发生变化,这些函数返回的值也不会改变。
Camera.Parameters p = camera.getParameters();
double thetaV = Math.toRadians(p.getVerticalViewAngle());
double thetaH = Math.toRadians(p.getHorizontalViewAngle());
Two things cause your "effective" view angle to change: zoom, and using a preview aspect ratio that does not match the camera aspect ratio.
有两件事会导致您的“有效”视角发生变化:缩放和使用与相机纵横比不匹配的预览纵横比。
Basic Math
基础数学
The trigonometry of field-of-view (Θ) is fairly simple:
视场 (Θ) 的三角函数相当简单:
tan(Θ/2) = x / 2z
x = 2z tan(Θ/2)
tan(Θ/2) = x / 2z
x = 2z tan(Θ/2)
x is the linear distance viewable at distance z; i.e., if you held up a ruler at distance z=1 meter, you would be able to see x meters of that ruler.
x 是在距离 z 处可见的线性距离;即,如果您在距离 z=1 米处举起尺子,您将能够看到该尺子的 x 米。
For instance on my camera, horizontal field of view is 52.68° while vertical field of view is 40.74°. Convert these to radians and plug them into the formula with an arbitrary z value of 100m, and you get x values of 99.0m(horizontal) and 74.2m(vertical). This is a 4:3 aspect ratio.
例如在我的相机上,水平视场为 52.68°,而垂直视场为 40.74°。将这些转换为弧度并将它们代入公式中,任意 z 值为 100m,您将得到 99.0m(水平)和 74.2m(垂直)的 x 值。这是一个 4:3 的纵横比。
Zoom
飞涨
Applying this math to zoom levels is only slightly harder. Now, x remains constant and it is z that changes in a known ratio; we must determine Θ.
将此数学应用于缩放级别只是稍微困难一些。现在,x 保持不变,z 以已知比率变化;我们必须确定 Θ。
tan (Θ/2) = x / (2z)
tan (Θ'/2) = x / (2z')
Θ' = 2 atan((z / z') tan(Θ/2))
tan (Θ/2) = x / (2z)
tan (Θ'/2) = x / (2z')
Θ' = 2 atan((z / z') tan(Θ/2))
Where z is the base zoom level (100), z' is the current zoom level (from CameraParameters.getZoomRatios), Θ is the base horizontal/vertical field of view, and Θ' is the effective field of view. Adding on degree->radian conversions makes this rather verbose.
其中 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);
Aspect Ratio
纵横比
While the typical camera is a 4:3 aspect ratio, the preview may also be available in 5:3 and 16:9 ratios and this seems to be accomplished by actually extending the horizontal field of view. This appears to be undocumented, hence unreliable, but by assuming that's how it works we can calculate the field of view.
虽然典型的相机是 4:3 的纵横比,但也可以以 5:3 和 16:9 的比例进行预览,这似乎是通过实际扩展水平视野来实现的。这似乎没有记录,因此不可靠,但通过假设它是如何工作的,我们可以计算视野。
The math is similar to the zoom calculations; however, in this case z remains constant and it is x that changes. By assuming that the vertical view angle remains unchanged while the horizontal view angle is varied as the aspect ratio changes, it's possible to calculate the new effective horizontal view angle.
数学类似于缩放计算;然而,在这种情况下,z 保持不变,而变化的是 x。假设垂直视角保持不变而水平视角随着纵横比的变化而变化,则可以计算出新的有效水平视角。
tan(Θ/2) = v / (2z)
tan(Θ'/2) = h / (2z)
2z = v / tan(Θ/2)
Θ' = 2 atan((h/v) tan(Θ/2))
tan(Θ/2) = v / (2z)
tan(Θ'/2) = h / (2z)
2z = v / tan(Θ/2)
Θ' = 2 atan((h/v) tan(Θ/2))
Here h/v is the aspect ratio and Θ is the base vertical field of view, while Θ' is the effective horizontal field of view.
这里 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);
As I said above, since this appears to be undocumented, it is simply a guess that it will apply to all devices; it should be considered a hack. The correct solution would be splitting off a new set of functions getCurrentHorizontalViewAngle and getCurrentVerticalViewAngle.
正如我上面所说,由于这似乎没有记录,所以只是猜测它适用于所有设备;它应该被认为是一个黑客。正确的解决方案是拆分一组新的函数 getCurrentHorizontalViewAngle 和 getCurrentVerticalViewAngle。
回答by Max
I have a Droid Incredible as well. Android 2.2 introduced the functions you are looking for. In my code, I have:
我也有一个 Droid Incredible。Android 2.2 引入了您正在寻找的功能。在我的代码中,我有:
public double getHVA() {
return camera.getParameters().getHorizontalViewAngle();
}
public double getVVA() {
return camera.getParameters().getVerticalViewAngle();
}
However, these require that you have the camera open. I'd be interested to know if there is a "best practices" way to not have to open the camera each time to get those values.
但是,这些要求您打开相机。我很想知道是否有一种“最佳实践”方法可以不必每次都打开相机来获取这些值。
@David Zaslavsky - how? What is the mathematical relationship between the zoom levels? I can't find it anywhere (I asked in this question: What do the Android camera zoom numbers mathematically represent?)
@David Zaslavsky - 怎么样?缩放级别之间的数学关系是什么?我在任何地方都找不到(我在这个问题中问过:Android 相机变焦数字在数学上代表什么?)