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

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

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

введите описание изображения здесь

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

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

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

α = 2 * atan (l / 2d)

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

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

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

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

Две вещи вызывают изменение вашего «эффективного» угла обзора: увеличение и использование пропорции предварительного просмотра, которая не соответствует соотношению сторон камеры.

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

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

tan (Θ / 2) = x / 2z

x = 2z tan (Θ / 2)

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

Например, на моей камере горизонтальное поле зрения составляет 52,68 °, а вертикальное поле зрения – 40,74 °. Преобразуйте их в радианы и подключите их к формуле с произвольным значением z 100 м, и вы получите значения х 99,0 м (по горизонтали) и 74,2 м (по вертикали). Это соотношение сторон 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.

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

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

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

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

Interesting Posts

Как я могу исключить определенный файл из источника управления TFS

Как увеличить размер страницы PDF для добавления водяного знака?

Как очистить текущее состояние «только для чтения» на USB-накопителе, которое я установил с помощью Rufus?

remove_if для std :: map

Как вы выполняете предельный запрос в HQL?

Как использовать пользовательские ключи с протоколом Swift 4 Decodable?

Как я могу установить cron для запуска определенных команд каждые полтора часа?

Каков правильный способ использования C ++ 11?

Как отсортировать ArrayList?

Как я могу создать криптографически безопасное псевдослучайное число в C #?

Бесплатный способ обмена большими файлами (50 МБ) через Интернет?

На каком языке написана компилятор Java и JVM?

Есть ли способ «взломать» окна 10, чтобы использовать всю мощность процессора в одной задаче или процессе?

Объединение нескольких коммитов перед нажатием кнопки Git

Проблема с wav в Java

Давайте будем гением компьютера.