2010-07-16 7 views

Répondre

10

Sauf s'il y a un appel API pour cela (je ne suis pas un programmeur Android, je ne sais pas), je voudrais juste prendre une image d'une règle à une distance connue, voir combien de la règle est montré dans l'image, puis utilisez la trigonométrie pour trouver l'angle comme this:

enter image description here

maintenant vous avez les deux distances l et d de la figure. Avec certains goniométrie simple, on peut obtenir:

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

donc

α = 2 * atan (l/2d)

Ainsi, avec cette formule, vous pouvez calculer le champ de vision horizontal de votre caméra. Bien sûr, la mesure de la verticale f.o.v. va exactement de la même façon sauf que vous devez ensuite voir l'objet dans sa position verticale. Ensuite, vous pouvez le coder en dur comme une constante dans votre programme. (Une constante nommée, bien sûr, donc il serait facile de changer :-p)

+1

Mieux encore, rendez-le configurable par l'utilisateur afin que les personnes qui n'ont pas de Droid Incredible puissent l'ajuster/calibrer. – EboMike

+0

Cette valeur changerait avec le niveau de zoom, bien sûr. –

+0

@emddudley: vrai, je n'ai jamais pensé au téléphone ayant un niveau de zoom. Bien que l'angle de vue soit donné à n'importe quel niveau de zoom, il devrait être possible de le calculer à tout autre niveau de zoom. –

9

J'ai aussi un Droid Incredible. Android 2.2 a présenté les fonctions que vous recherchez. Dans mon code, j'ai:

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

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

Cependant, ceux-ci exigent que vous ayez l'appareil photo ouvert. Je serais intéressé de savoir s'il existe un moyen de «bonnes pratiques» de ne pas avoir à ouvrir la caméra à chaque fois pour obtenir ces valeurs.

@David Zaslavsky - comment? Quelle est la relation mathématique entre les niveaux de zoom? Je ne peux pas le trouver n'importe où (j'ai demandé dans cette question: What do the Android camera zoom numbers mathematically represent?)

55

Les fonctions Camera.Parameters getHorizontalViewAngle() et getVerticalViewAngle() vous fournissent les angles de vue de base. Je dis "base", car ceux-ci ne s'appliquent qu'à la caméra elle-même dans un état non zoomé, et les valeurs renvoyées par ces fonctions ne changent pas même lorsque l'angle de vue le fait.

Camera.Parameters p = camera.getParameters(); 
double thetaV = Math.toRadians(p.getVerticalViewAngle()); 
double thetaH = Math.toRadians(p.getHorizontalViewAngle()); 

Deux choses provoquent l'angle de vue « efficace » pour changer: zoom, et en utilisant un rapport d'aspect de prévisualisation qui ne correspond pas au format de la caméra.

Math Basic

Le trigonométrie de champ de vision (Θ) est assez simple:

tan (Θ/2) = x/2z

x = 2z tan (Θ/2)

x est la distance linéaire pouvant être visualisée à la distance z; c'est-à-dire que si vous teniez une règle à une distance z = 1 mètre, vous pourriez voir x mètres de cette règle.

Par exemple sur mon appareil photo, le champ de vision horizontal est de 52.68 ° tandis que le champ de vision vertical est de 40,74 °. Convertissez-les en radians et branchez-les dans la formule avec une valeur z arbitraire de 100m, et vous obtenez des valeurs x de 99,0m (horizontal) et 74,2m (vertical). C'est un rapport d'aspect 4: 3.

Zoom

En appliquant ce calcul pour zoomer les niveaux est légèrement plus difficile. Maintenant, x reste constant et c'est z qui change dans un rapport connu; nous devons déterminer Θ.

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

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

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

où z est le niveau de zoom de base (100), z' est le niveau de zoom actuel (de CameraParameters.getZoomRatios), Θ est le champ de base horizontal/vertical de vue , et Θ 'est le champ de vision effectif. L'ajout de conversions degré-> radian rend cela plutôt verbeux.

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

Alors que la caméra typique est un 4: 3 aspect ratio, la prévisualisation peut également être disponible en 5: 3 et 16: 9 et cela semble être accompli en prolongeant effectivement la champ de vision horizontal. Cela semble être non documenté, donc peu fiable, mais en supposant que c'est ainsi que cela fonctionne, nous pouvons calculer le champ de vision.

Le calcul est similaire aux calculs de zoom; cependant, dans ce cas, z reste constant et c'est x qui change. En supposant que l'angle de vue vertical reste inchangé tandis que l'angle de vue horizontal est modifié lorsque le rapport d'aspect change, il est possible de calculer le nouvel angle de vue horizontal effectif.

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

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

2z = v/tan (Θ/2)

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

ici h/v est le rapport d'aspect et Θ est le champ vertical de la base de vue, tandis que Θ' est le champ de vision horizontal effectif.

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

Comme je l'ai dit plus haut, car cela semble être en situation irrégulière, il est tout simplement une estimation qu'il appliquera à tous les appareils; cela devrait être considéré comme un hack. La solution correcte serait de séparer un nouvel ensemble de fonctions getCurrentHorizontalViewAngle et getCurrentVerticalViewAngle.

+1

Les résultats getHorizontalViewAngle() et getVerticalViewAngle() peuvent-ils être approuvés pour une grande variété de périphériques? –

+1

Existe-t-il des méthodes similaires (getVertical/HorizontalViewingAngle() dans l'API camera2? Je ne les ai pas vues, et je me demandais si elles me manquaient ou si elles n'étaient pas présentes.Probablement dans CameraCharacteristics? – Innova

+0

@Innova, je me demande la même chose - peut-être que ces valeurs étaient trop simplistes, mais j'ai parcouru toute la documentation de camera2, et je n'ai trouvé aucune façon simple de le faire. – TonyTheJet

Questions connexes