2010-07-16 20 views

risposta

10

A meno che non ci sia qualche chiamata API per questo (non sono un programmatore Android, non lo saprei), vorrei semplicemente scattare una foto di un righello da una distanza nota, vedere quanta parte del righello è mostrata nella foto, quindi utilizzare la trigonometria per trovare l'angolo come this:

enter image description here

ora avete le due distanze L e d della figura. Con qualche semplice goniometry, si possono ottenere:

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

quindi

α = 2 * atan (l/2d)

Quindi con questa formula puoi calcolare il campo visivo orizzontale della tua videocamera. Naturalmente misurando la verticale f.o.v. procede esattamente allo stesso modo, tranne per il fatto che è necessario visualizzare l'oggetto nella sua posizione verticale.

Quindi è possibile codificarlo come una costante nel programma. (Una costante di nome, ovviamente, quindi sarebbe facile da cambiare :-p)

+1

Meglio ancora, renderlo configurabile dall'utente, così le persone che non hanno un Droid Incredible possono regolarlo/calibrarlo. – EboMike

+0

Questo valore cambierebbe naturalmente con il livello di zoom. –

+0

@emddudley: vero, non ho mai pensato al telefono con un livello di zoom. Sebbene sia dato l'angolo di visuale a qualsiasi livello di zoom, dovrebbe essere possibile calcolarlo a qualsiasi altro livello di zoom. –

9

Ho anche un Droid Incredibile. Android 2.2 ha introdotto le funzioni che stai cercando. Nel mio codice, ho:

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

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

Tuttavia, questi richiedono di avere la fotocamera aperta. Sarei interessato a sapere se esiste un modo "best practice" per non dover aprire la telecamera ogni volta per ottenere quei valori.

@David Zaslavsky - come? Qual è la relazione matematica tra i livelli di zoom? Non riesco a trovarlo da nessuna parte (ho chiesto in questa domanda: What do the Android camera zoom numbers mathematically represent?)

55

Le funzioni Camera.Parametri getHorizontalViewAngle() e getVerticalViewAngle() forniscono gli angoli della vista di base. Dico "base", perché si applicano solo alla fotocamera stessa in uno stato non a zombi, e i valori restituiti da queste funzioni non cambiano anche quando lo stesso angolo di vista lo fa.

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

Due cose causano l'angolo "efficace" al fine di cambiare: zoom, e utilizzando un rapporto di aspetto di anteprima che non corrisponde al rapporto di aspetto della fotocamera.

Basic Math

La trigonometria di campo di vista (Θ) è abbastanza semplice:

tan (Θ/2) = x/2z

x = 2z tan (Θ/2)

x è la distanza lineare visibile alla distanza z; Ad esempio, se hai tenuto un righello alla distanza z = 1 metro, saresti in grado di vedere x metri di quel righello.

Per esempio sulla mia macchina fotografica, il campo visivo orizzontale è 52.68 ° mentre il campo visivo verticale è 40,74 °. Converti questi in radianti e inseriscili nella formula con un valore z arbitrario di 100 m, e ottieni valori x di 99.0 m (orizzontale) e 74.2 m (verticale). Questo è un rapporto di aspetto 4: 3.

Zoom

Applicando questa matematica per diminuire i livelli è solo leggermente più difficile. Ora, x rimane costante ed è z che cambia in un rapporto noto; dobbiamo determinare Θ.

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

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

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

dove z è il livello di base di zoom (100), z' è il livello di zoom corrente (da CameraParameters.getZoomRatios), Θ è il campo orizzontale di base/verticale di vista e Θ 'è il campo visivo effettivo. Aggiungendo su gradi-> conversioni radianti rende questo piuttosto prolisso.

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

Proporzioni

Mentre la fotocamera tipico è un rapporto di 4: 3, l'anteprima potrebbe anche essere disponibile in 5: 3 e 16: 9 e questo sembra essere compiuta in realtà estendendo la campo visivo orizzontale. Questo sembra non documentato, quindi inaffidabile, ma assumendo che è come funziona possiamo calcolare il campo visivo.

La matematica è simile ai calcoli dello zoom; tuttavia, in questo caso z rimane costante ed è x che cambia. Supponendo che l'angolo di visuale verticale rimanga invariato mentre l'angolo di visuale orizzontale viene modificato al variare delle proporzioni, è possibile calcolare il nuovo angolo di vista orizzontale effettivo.

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

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

2z = v/tan (Θ/2)

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

Qui h/v è il rapporto di aspetto e Θ è il campo verticale base della vista, mentre Θ' è il efficace campo visivo orizzontale.

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

come ho detto sopra, dal momento che questo sembra essere privi di documenti, è semplicemente una congettura che applicherà a tutti i dispositivi; dovrebbe essere considerato un hack. La soluzione corretta sarebbe la divisione di una nuova serie di funzioni getCurrentHorizontalViewAngle e getCurrentVerticalViewAngle.

+1

I risultati getHorizontalViewAngle() e getVerticalViewAngle() possono essere considerati attendibili per un'ampia varietà di dispositivi? –

+1

Esistono metodi simili (getVertical/HorizontalViewingAngle() nell'API camera2? Non li ho visti e mi chiedevo se li avessi persi o se non fossero presenti.Probabilmente in CameraCharacteristics? – Innova

+0

@Innova, mi sto chiedendo la stessa cosa - potrebbe essere che quei valori fossero eccessivamente semplicistici, ma ho cercato in tutta la documentazione di camera2, e non ho trovato alcun modo semplice per farlo. – TonyTheJet

Problemi correlati