Гомография Opencv для поиска глобальных координат xy из координат xy пикселей

Я пытаюсь найти матрицу преобразования H, чтобы я мог умножить (x, y) координаты пикселей и получить (x, y) координаты реального мира. Вот мой код:

import cv2
import numpy as np
from numpy.linalg import inv
if __name__ == '__main__' :
D=[159.1,34.2]
I=[497.3,37.5]
G=[639.3,479.7]
A=[0,478.2]
# Read source image.
im_src = cv2.imread('/home/vivek/june_14.png')
# Four corners of the book in source image
pts_src = np.array([D,I,G,A])

# Read destination image.
im_dst = cv2.imread('/home/vivek/june_14.png')

# Four corners of the book in destination image.
print "img1 shape:",im_dst.shape
scale=1
O=[0.0,0.0]
X=[134.0*scale,0]
Y=[0.0,184.0*scale]
P=[134.0*scale,184.0*scale]
# lx = 75.5 * scale
# ly = 154.0 * scale
pts_dst = np.array([O,X,P,Y])

# Calculate Homography
h, status = cv2.findHomography(pts_src, pts_dst)

print "homography:",h
print "inv of H:",inv(h)
print "position of the blob on the ground xy plane:",np.dot(np.dot(h,np.array([[323.0],[120.0],[1.0]])),scale)


# Warp source image to destination based on homography

im_out = cv2.warpPerspective(im_src, h, (im_dst.shape[1],im_dst.shape[0]))

# Display images
cv2.imshow("Source Image", im_src)
cv2.imshow("Destination Image", im_dst)
cv2.imshow("Warped Source Image", im_out)
cv2.imwrite("im_out.jpg", im_out)
cv2.waitKey(0)

Глобальные xy, которые я получаю, очень неправильные. Я где-то что-то не так делаю?


person Vivek Annem    schedule 16.06.2017    source источник
comment
Извините, а что такое переменные D,I,G,A,O,X,P,Y? Что они должны представлять? В любом случае, когда вы вычисляете координаты (x,y) реального мира, вы получаете однородные точки, которые эквивалентны при масштабировании --- другими словами, они могут быть масштабированы и по-прежнему будут считаться одной и той же точкой. . Но вам нужно x,y точки, а не масштабированные, поэтому нужно делить по шкале. Все три вектора масштабируются на одинаковую величину, поэтому вы можете использовать последнюю запись для коэффициента масштабирования. Вы должны сделать pts = scale*np.dot(h,np.array([[323.0],[120.0],[1.0]])), а затем pts = pts/pts[-1].   -  person alkasm    schedule 16.06.2017
comment
OXPY - это реальные точки слова (начало O, X-134 дюйма вправо, P-134 дюйма вправо и 184 дюйма вниз, Y-184 дюйма вниз), а DIGA - соответствующие координаты пикселей на плоскости изображения.   -  person Vivek Annem    schedule 16.06.2017
comment
Мне жаль. Я не совсем понял масштабную часть.   -  person Vivek Annem    schedule 16.06.2017
comment
Кажется, я понимаю, что вы имели в виду. Позвольте мне проверить и посмотреть, получаю ли я правильные значения.   -  person Vivek Annem    schedule 16.06.2017
comment
Попробуйте код очень быстро и посмотрите, решит ли он вашу проблему — если да, я добавлю более подробный ответ. По сути, это неправда, что [x', y', 1] = H*[x, y, 1]; это [sx', sy', s] = H*[x, y, 1]. Но вам нужно, чтобы однородные точки заканчивались на 1, чтобы они были эквивалентны x,y координатам, поэтому вам нужно разделить на s однородные координаты.   -  person alkasm    schedule 16.06.2017
comment
Проблема решена. Большое спасибо, @AlexanderReynolds   -  person Vivek Annem    schedule 16.06.2017
comment
Я добавлю это как ответ. Рад, что это сработало!   -  person alkasm    schedule 16.06.2017


Ответы (2)


Длинный ответ

Гомографии — это 3x3 матрицы, а точки — это просто пары, 2x1, поэтому их невозможно сопоставить вместе. Вместо этого используются однородные координаты, что дает 3x1 векторов для умножения. Однако однородные точки можно масштабировать, представляя одну и ту же точку; то есть в однородных координатах (kx, ky, k) — это та же точка, что и (x, y, 1). Со страницы Википедии, посвященной однородным координатам:

Для точки (x, y) на евклидовой плоскости для любого ненулевого действительного числа Z тройка (xZ, yZ, Z) называется набором однородных координат точки. Согласно этому определению, умножение трех однородных координат на общий ненулевой множитель дает новый набор однородных координат для той же точки. В частности, (x, y, 1) является такой системой однородных координат для точки (x, y). Например, декартова точка (1, 2) может быть представлена ​​в однородных координатах как (1, 2, 1) или (2, 4, 2) . Исходные декартовы координаты восстанавливаются путем деления первых двух позиций на третью. Таким образом, в отличие от декартовых координат, одна точка может быть представлена ​​бесконечным числом однородных координат.

Очевидно, что в декартовых координатах этот скейлинг не выполняется; (x, y) не совпадает с точкой (xZ, yZ), если только Z = 0 или Z = 1. Поэтому нам нужен способ отображения этих однородных координат, которые могут быть представлены бесконечным числом способов, вплоть до декартовых координат, которые могут быть представлены только одним способом. К счастью, это очень просто: просто масштабируйте однородные координаты так, чтобы последнее число в тройке было 1.

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

Краткий ответ

Когда вы умножаете однородные координаты на гомографию, вам нужно их масштабировать:

sx'       x
sy' = H * y
s         1

Итак, чтобы вернуться к декартовым координатам, разделите новые однородные координаты на s: (sx', sy', s)/s = (x', y', 1) и затем (x', y') — нужные точки.

Более короткий ответ

Используйте встроенную функцию OpenCV convertPointsFromHomogeneous() для преобразования точек из однородных 3-векторов в декартовы 2-векторы.

person alkasm    schedule 16.06.2017

person    schedule
comment
Только что попробовал этот ответ, он очень помогает, исправленная версия def toworld(x,y):imagepoint = [x, y, 1];worldpoint = np.array(np.dot(inversehomographymatrix,imagepoint));scalar = worldpoint[2];xworld = worldpoint[0]/scalar;yworld = worldpoint[1]/scalar;return xworld, yworld - person CocoaBob; 23.07.2018