Делаю слежение за машиной на видео. Я пытаюсь определить, сколько метров он прошел.
Я случайным образом вытащил 7 точек из видеокадра. Я указал точку 1 в качестве источника
Затем в соответствующей перспективе Google Maps я рассчитал расстояния 6 точек от начала координат (дельта x и дельта y).
Затем я выполнил следующее
pts_src = np.array([[417, 285], [457, 794], [1383, 786], [1557, 423], [1132, 296], [759, 270], [694, 324]])
pts_dst = np.array([[0,0], [-3, -31], [30, -27], [34, 8], [17, 15], [8, 7], [6, 1]])
h, status = cv2.findHomography(pts_src, pts_dst)
a = np.array([[1032, 268]], dtype='float32')
a = np.array([a])
# finally, get the mapping
pointsOut = cv2.perspectiveTransform(a, h)
Когда я тестировал отображение точки 7, результаты были неверными.
Я что-то упустил? Или я использую неправильный метод? Спасибо
Я отметил точки, и вот отображение
Столбец x,y представляет пиксели на изображении. Столбец измерений представляет собой расстояние от начала координат до точки в метрах. Я в основном, используя карты Google, преобразовал геокод в UTM и вычислил разницу x и y.
Я попытался ввести 7-ю точку и получил [[[14.682752 9.927497]]] в качестве вывода, что довольно далеко по оси x.
Любая идея, если я делаю что-то не так?
Камеры не являются идеальными камерами-обскурой, и поэтому гомография не может зафиксировать реальное преобразование.
Для камер с малым углом результат довольно близок, но для камеры «рыбий глаз» результат может быть очень далеким.
Кроме того, по моему опыту, только теоретическая модель искажения объектива, найденная в литературе, не очень точна с реальными объективами (многоэлементными, которые делают «странные» вещи для компенсации бочкообразного/подушкообразного искажения). Сегодня также актуально использование несферических линз, где трансформация может быть какой угодно.
Чтобы получить точные результаты, единственным решением, которое я нашел, было отображение функции преобразования с использованием функции интерполяционного сплайна.
В вашем случае я бы сказал, что проблема во входных данных: учитывая квазичетырехугольник, образованный точками 6, 3, 1, 2
Если расстояние AD в метрах равно 36,9, то как расстояние B-C может быть равно 53,8 метра?
Возможно, проблема в том, как вы собирали данные, или в том, что карты Google нельзя считать надежными для таких небольших измерений.
Решением может быть просто измерение относительных расстояний точек, а затем определение их координат на плоскости из этой матрицы расстояний.
Чтобы проверить, я написал простой нелинейный решатель методом наименьших квадратов (работает путем стохастического восхождения на холм), используя для проверки изображение своего пола. Через несколько секунд (она написана на Python, поэтому скорость — не самая лучшая ее функция) можно решить общее уравнение точечной плоской камеры:
pixel_x = (world_x*m11 + world_y*m12 + m13) / w
pixel_y = (world_x*m21 + world_y*m22 + m23) / w
w = (x*m31 + y*m32 + m33)
m11**2 + m12**2 + m13**2 = 1
и я могу получить камеру с максимальной ошибкой менее 4 пикселей (на изображении 4k).
Однако с данными ТВОЙ я не могу получить ошибку меньше 120 пикселей. Лучшая матрица, которую я нашел для ваших данных:
0.0704790534896005 -0.0066904288370295524 0.9974908226049937
0.013902632209214609 -0.03214426521221147 0.6680756144949469
6.142954035443663e-06 -7.361135651590592e-06 0.002007213927080277
Решая ваши данные используя только точки 1, 2, 3 и 6 я получаю конечно точное числовое решение (при четырех общих точках есть одна точная планарная камера) но изображение явно совершенно неправильное (сетка должна лежать на плоскости улицы) :
Спасибо за ответ. Хм, я в растерянности от последнего утверждения. Я не пытаюсь получить точные результаты, но как можно ближе. Камера не "рыбий глаз". На самом деле это обычная камера, установленная на углу для наблюдения за перекрестком. Я пытаюсь нанести на карту точки, чтобы я мог измерить скорость автомобиля
@Snake: наше использование требует высокой точности (~ 0,01%), потому что изображение с камеры используется для управления режущей машиной; Однако для этого требуется несколько сложная процедура калибровки. В вашем случае, если я правильно понял, должно быть проще. Возможно, вам следует добавить пример кадра к вопросу и ошибке, которую вы получаете.
Я добавил пример того, что я имею в виду, включая то, как я получил свои данные. Есть идеи?
Спасибо за редактирование. Не могли бы вы подробнее рассказать о вашей последней строке? Может быть, если вы объясните дальше, что вы имеете в виду. Кроме того, почему 36,9 и 53,8 не имеют смысла? Углы C и B являются самыми дальними углами. Вы думаете, что они не так далеко, как 13 метров?
@Snake: я увидел это и решил проверить, не в данных ли проблема. Я написал решатель и протестировал свои напольные плитки, и я могу получить довольно хорошую точность (только точное определение модели камеры, без компенсации искажений). Однако с вашими данными я не могу получить ошибку ниже 120 пикселей. Я действительно убежден, что ваш вклад проблематичен. Я решил ваши данные, используя только четыре точки, и наложил то, что найдено, в виде сетки...
Вы были абсолютно правы. Вход казался выключенным. В этот раз я использовал Google Earth. И вместо дельты x и дельты y в метрах я использовал Lat, Long в качестве точки назначения. Я провел несколько тестов и получил очки чертовски близко. Теперь мне нужно выяснить, как преобразовать 2 точки широты и долготы в расстояние в метрах через python (но это другая проблема). Спасибо :)))
Любой комментарий или помощь?