Определить угол обзора камеры смартфона

Я пытаюсь определить размер поля обзора камеры смартфона Droid Incredible. Мне нужно знать это значение для приложения, которое я разрабатываю. Кто-нибудь знает, как я могу узнать / рассчитать это программно?

3 ответа

Решение

Если бы не было какого-то API-вызова для этого (я не программист на Android, я бы не знал), я просто сделал бы снимок линейки на известном расстоянии, чтобы посмотреть, какая часть линейки показана на рисунке, затем используйте тригонометрию, чтобы найти такой угол:

Теперь у вас есть два расстояния l и d от фигуры. С помощью некоторой простой гониометрии можно получить:

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

следовательно

α = 2* атан (л /2д)

Таким образом, с помощью этой формулы вы можете рассчитать горизонтальное поле зрения вашей камеры. Конечно, измерение вертикального поля зрения происходит точно так же, за исключением того, что вам необходимо просматривать объект в вертикальном положении.

Затем вы можете жестко закодировать его как константу в вашей программе. (Именованная константа, конечно, так что было бы легко изменить:-p)

Функции Camera.Parameters getHor horizontalViewAngle() и getVerticalViewAngle() предоставляют базовые углы обзора. Я говорю "базовый", потому что они применяются только к самой камере в состоянии без увеличения, а значения, возвращаемые этими функциями, не изменяются даже при изменении угла обзора.

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

Изменение "эффективного" угла обзора приводит к двум вещам: увеличению и использованию формата предварительного просмотра, который не соответствует формату камеры.

Базовая математика

Тригонометрия поля зрения (Θ) довольно проста:

tan (Θ/2) = x / 2z

x = 2z загар (Θ/2)

х - линейное расстояние, видимое на расстоянии z; то есть, если вы держите линейку на расстоянии z=1 метр, вы сможете увидеть x метров этой линейки.

Например, на моей камере горизонтальное поле зрения составляет 52,68°, а вертикальное поле зрения - 40,74°. Преобразуйте их в радианы и вставьте их в формулу с произвольным значением z, равным 100 м, и вы получите значения x, равные 99,0 м (по горизонтали) и 74,2 м (по вертикали). Это соотношение сторон 4:3.

Увеличить

Применение этой математики к уровням масштабирования лишь немного сложнее. Теперь x остается постоянным, и z изменяется в известном соотношении; мы должны определить Θ.

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

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

Θ'= 2 атан ((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 атан ((ч / в) тан (Θ/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);

Как я уже говорил выше, поскольку это выглядит недокументированным, это просто предположение, что оно будет применяться ко всем устройствам; это следует считать хаком. Правильным решением было бы разделение нового набора функций getCurrentHor horizontalViewAngle и getCurrentVerticalViewAngle.

У меня также есть дроид Невероятный. Android 2.2 представил функции, которые вы ищете. В моем коде у меня есть:

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

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

Однако для этого необходимо, чтобы камера была открыта. Мне было бы интересно узнать, есть ли способ "наилучшей практики", чтобы каждый раз не открывать камеру, чтобы получить эти значения.

@ Давид Заславский - как? Какова математическая связь между уровнями масштабирования? Я нигде не могу его найти (я спросил в этом вопросе: что математически представляют цифры масштабирования камеры Android?)

Другие вопросы по тегам