Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Determine angle of view of smartphone camera

Tags:

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?

like image 959
GobiasKoffi Avatar asked Jul 16 '10 03:07

GobiasKoffi


People also ask

What is angle of view of mobile camera?

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. For instance on my camera, horizontal field of view is 52.68° while vertical field of view is 40.74°.

How is phone camera quality measured?

Checking megapixel count on an Android phone Just open the camera app, click the settings icon (the small cog) and you should find the megapixel information listed under the heading "Photo size".


2 Answers

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

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.

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.

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 Θ.

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.

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.

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.

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.

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.

like image 178
5 revs Avatar answered Sep 28 '22 21:09

5 revs


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:

enter image description here

now you have the two distances l and d from the figure. With some simple goniometry, one can obtain:

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

hence

α = 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.

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)

like image 28
David Z Avatar answered Sep 28 '22 20:09

David Z