Как рассчитать конкретное расстояние внутри изображения?

Извините за мой плохой английский. У меня есть следующая проблема:

1

Скажем, камера моего мобильного устройства показывает это изображение.

На рисунке вы можете видеть 4 разных положения. Мне известна всякая позиция (долгота, широта).

Теперь я хочу знать, где на картинке находится конкретная позиция. Например, я хочу иметь прямоугольник 20 метров впереди и 5 метров слева от меня. Я просто знаю широту/долготу этого момента, но я не знаю, где я должен разместить его внутри изображения (x, y). Например, POS3 на (0,400), на мой взгляд. POS4 - (600 400) и так далее.

Где я должен поставить новую точку, которая составляет 20 метров впереди и 5 метров слева от меня? (Итак, мой вход: (LatXY, LonXY), и мой результат должен быть (x, y) на экране)

Я также получил высоту камеры и углы оси x, y и z от камеры.

Могу ли я использовать простые математические операции для решения этой проблемы?

Большое спасибо!

Ответ 1

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

Во-первых, вы можете игнорировать информацию направления с устройства, если вы выберете. Если у вас есть пять местоположений (POS1 - POS4 и камера, в согласованном наборе координат, у вас есть все, что вам нужно. На самом деле вам даже не нужны все эти точки.

Замечание о согласованных координатах. В своем масштабе, как только вы используете преобразование lat и long to meters, используя cos (lat) для вашего масштабирующего коэффициента, вы должны уметь рассматривать всех с точки зрения "плоской земли". Вам просто нужно помнить, что плоскость x-y камеры является примерно глобальной плоскостью x-z.

Концептуальный фон На приведенной ниже диаграмме показана проекция точек на плоскость изображения. Dz, используемый для перспективы, может быть получен непосредственно с использованием доли расстояния между дальними точками и близкими точками по сравнению с их физическим расстоянием. В простом случае, где линия POS1-POS2 параллельна линии POS3-POS4, фактор перспективы - это просто соотношение масштабирования двух линий:

Scale (POS1, POS2) = pixel distance (pos1, pos2) / Physical distance (POS1, POS2)
Scale (POS3, POS4) = pixel distance (pos3, pos4) / Physical distance (POS3, POS4)
Perspective factor = Scale (POS3, POS4) / Scale (POS1, POS2)

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

Factor(rect) ~= [(Rect.z - (POS3, POS4).z / ((POS1, POS2).z - (POS3, POS4).z)] * Perspective factor.

Ответ

Перспективное преобразование линейно относительно расстояния от фокальной точки в направлении обзора. Диаграмма ниже рисуется с осью X, параллельной плоскости изображения, и осью Y, направленной в направлении обзора. В этой системе координат для любой точки P и плоскости изображения на любом расстоянии от начала координат проецируемая точка p имеет координату X p.x, которая пропорциональна P.x/P.y. Эти значения могут быть линейно интерполированы.

На диаграмме tp - желаемая проекция целевой точки. для получения tp.x, интерполировать между, например, pos1.x и pos3.x, используя настройки для расстояния, следующим образом:

tp.x = pos1.x + ((pos3.x-pos1.x)*((TP.x/TP.y)-(POS1.x/POS1.y))/((POS3.x/POS3.y)-(POS1.x/POS1.y))

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

Дальнейшее уточнение

Использование большего количества данных означает возможность компенсации большего количества ошибок. С учетом нескольких точек местоположение камеры и ориентация можно откалибровать с помощью метода Tienstra. Кратким доказательством этого подхода (с использованием барицентрических координат) можно найти здесь.

Поскольку требуемое преобразование линейно основано на однородных координатах, вы можете применить барицентрические координаты для интерполяции на основе любых трех или более точек, учитывая их X, Y, Z, W в однородном 3-пространстве и их координатах (x, y) в пространстве изображений. Чем ближе точки к точке назначения, тем менее значительными могут быть нелинейности, поэтому в вашем примере вы будете использовать POS 1 и POS3, так как прямоугольник слева и POS2 или POS4 в зависимости от относительного расстояния.

(Барицентрические координаты, скорее всего, наиболее известны как метод, используемый для интерполяции цветов в треугольнике (фрагменте) в 3D-графике.)

Изменить: Барицентрические координаты по-прежнему требуют однородного координатного коэффициента W, что является еще одним способом выражения коррекции перспективы для расстояния от фокальной точки. Подробнее см. в этой статье на GameDev.

Два взаимосвязанных вопроса SO: перспективная коррекция координат текстур в 3d и Barycentric maps mapping mapping. This diagram may help in explaining the interpolation of image coordinates based on global coordinates

Ответ 2

Я вижу пару проблем.

Единственная реальная ошибка заключается в том, что вы масштабируете свою проекцию _canvasWidth/2 и т.д. вместо того, чтобы переводить это далеко от основной точки - добавьте это значение к прогнозируемому результату, умножение похоже на "масштабирование", что далеко в проекции.

Во-вторых, дело в глобальном декартовом пространстве координат - плохая идея. Используя формулы, которые вы используете, разница между (60.1234, 20.122) и (60.1235, 20.122) (т.е. Небольшая разность широт) вызывает изменения одинаковой величины во всех трех осях, которые не кажутся правильными.

Это более простой подход к компьютерной графике: установите камеру как источник вашего "пространства камеры" и преобразуйте между объектами мира и пространствами камеры, получив расстояние (или подобное расстояние) между местоположением вашей камеры и расположение объекта. См. Здесь: http://www.movable-type.co.uk/scripts/latlong.html

В-третьих, ваши проекции перспективных проекций предназначены для идеальной камеры с отверстиями, которой, вероятно, нет. Это будет лишь небольшая коррекция, но чтобы быть точным, вам нужно выяснить, как дополнительно применять проекцию, соответствующую внутренним параметрам камеры вашей камеры. Есть два способа сделать это: вы можете сделать это как пост-умножение на уже имеющуюся схему или вы можете перейти от умножения на матрицу 3x3 на полную полноэкранную матрицу 4x4: http://en.wikipedia.org/wiki/Camera_matrix с параметрами.

Используя этот подход, проекция в перспективе симметрична относительно начала координат - если вы не проверяете глубину z, вы будете проектировать точки за собой на экран, как если бы они были тем же самым расстоянием z перед вами.

Затем, наконец, я не уверен в API Android, но убедитесь, что вы получаете истинное северное опоры, а не магнитное седло. Некоторые платформы возвращаются либо в зависимости от аргумента или конфигурации. (И ваши степени в радианах, если то, что хотят API и т.д. - глупые вещи, но я потерял часы, отлаживая меньше:)).

Ответ 3

Если вы знаете точки в кадре камеры и координаты реального мира, достаточно простой линейной алгебры. Пакет, такой как OpenCV, будет обладать этим типом функциональности, или, альтернативно, вы можете сами создать матрицы проецирования:

http://en.wikipedia.org/wiki/3D_projection

Как только у вас есть множество точек, это так же просто, как заполнение нескольких векторов для решения системы уравнений. Это даст вам проекционную матрицу. Если у вас есть проекционная матрица, вы можете предположить, что 4 точки являются плоскими. Умножьте любую трехмерную координату, чтобы найти соответствующую координату плоскости 2D изображения.