DroidIncredibleスマートフォンのカメラの視野の大きさを調べようとしています。開発中のアプリケーションのこの値を知る必要があります。プログラムでそれを見つけて計算する方法を誰かが知っていますか?
そのためのAPI呼び出しがない限り(私はAndroidプログラマーではない、わかりません))、既知の距離から定規の写真を撮るだけです。定規のが写真に示されているので、三角法を使用して次のような角度を見つけます this :
これで、図から2つの距離lとdが得られました。いくつかの簡単なゴニオメトリーで、次のことができます。
tan(α/ 2)=(l/2)/ d、
したがって、
α= 2 * atan(l/2d)
したがって、この式を使用すると、カメラの水平方向の視野を計算できます。もちろん、垂直視野を測定します。オブジェクトを垂直位置で表示する必要があることを除いて、まったく同じように動作します。
次に、それをプログラムの定数としてハードコーディングできます。 (もちろん、名前付き定数なので、簡単に変更できます:-p)
Camera.Parameters getHorizontalViewAngle()およびgetVerticalViewAngle()関数は、ベースビュー角度を提供します。これらはズームされていない状態のカメラ自体にのみ適用され、これらの関数によって返される値は、視野角自体が変化しても変化しないため、「ベース」と言います。
Camera.Parameters p = camera.getParameters();
double thetaV = Math.toRadians(p.getVerticalViewAngle());
double thetaH = Math.toRadians(p.getHorizontalViewAngle());
「有効な」視野角が変化する原因は2つあります。ズームと、カメラのアスペクト比と一致しないプレビューアスペクト比の使用です。
視野(Θ)の三角法はかなり単純です。
tan(Θ/ 2)= x/2z
x = 2ztan(Θ/ 2)
xは、距離zで表示可能な直線距離です。つまり、距離z = 1メートルで定規を持ち上げた場合、その定規のxメートルを見ることができます。
たとえば私のカメラでは、水平方向の視野は52.68°ですが、垂直方向の視野は40.74°です。これらをラジアンに変換し、100mの任意のz値を使用して数式にプラグインすると、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);
上で述べたように、これは文書化されていないように見えるので、すべてのデバイスに適用されると推測されます。それはハックと見なされるべきです。正しい解決策は、関数getCurrentHorizontalViewAngleとgetCurrentVerticalViewAngleの新しいセットを分割することです。
DroidIncredibleもあります。 Android 2.2はあなたが探している関数を紹介しました。私のコードでは、私は持っています:
public double getHVA() {
return camera.getParameters().getHorizontalViewAngle();
}
public double getVVA() {
return camera.getParameters().getVerticalViewAngle();
}
ただし、これらにはカメラを開いておく必要があります。これらの値を取得するために毎回カメラを開く必要がない「ベストプラクティス」の方法があるかどうかを知りたいと思います。
@David Zaslavsky-どうやって?ズームレベル間の数学的関係は何ですか?どこにも見つかりません(この質問で尋ねました: Androidカメラのズーム数は数学的に何を表していますか? )