Mam mapę wysokości obrazu, która informuje mnie o przesunięciu każdego piksela w kierunku Z. Moim celem jest spłaszczenie zniekształconego obrazu przy użyciu tylko jego mapy wysokości.Zniekształcenie obrazu przy użyciu mapy wysokości?
Jak miałbym to zrobić? Znam położenie kamery, jeśli to pomaga.
Aby to zrobić, myślałem o założeniu, że każdy piksel był punkt na płaszczyźnie, a następnie przetłumaczyć każdy z tych punktów w pionie według Z. wartości otrzymuję z mapy wysokości, a od zrobienia to tłumaczenie (wyobraź sobie, że patrzysz na punkty z góry, przesunięcie spowoduje, że punkt porusza się z twojej perspektywy).
Z tej rzutowanej zmiany mogłem wyodrębnić X i przesunięcie Y każdego piksela, które mogłem podać do cv.Remap()
.
Ale nie mam pojęcia, w jaki sposób mogę uzyskać rzutowane przesunięcie 3D punktu za pomocą OpenCV, nie mówiąc już o budowie mapy odsunięcia.
Oto moje obrazy odniesienia do tego, co robię:
wiem kąt laserów (45 stopni), a ze zdjęć kalibracji, mogę obliczyć wysokość książki naprawdę łatwo:
h(x) = sin(theta) * abs(calibration(x) - actual(x))
Robię to dla obu linii i liniowo interpolacji dwóch lin es do generowania powierzchni przy użyciu tego podejścia (kod Pythona. To wewnątrz pętli):
height_grid[x][y] = heights_top[x] * (cv.GetSize(image)[1] - y) + heights_bottom[x] * y
Mam nadzieję, że to pomoże;)
Teraz, to co muszę dewarp obraz. Wszystko, co dziwne rzeczy w środku projektów współrzędnych 3D na płaszczyznę aparatu, biorąc pod uwagę to stanowisko (i położenie aparatu, obracanie, itp):
class Point:
def __init__(self, x = 0, y = 0, z = 0):
self.x = x
self.y = y
self.z = z
mapX = cv.CreateMat(cv.GetSize(image)[1], cv.GetSize(image)[0], cv.CV_32FC1)
mapY = cv.CreateMat(cv.GetSize(image)[1], cv.GetSize(image)[0], cv.CV_32FC1)
c = Point(CAMERA_POSITION[0], CAMERA_POSITION[1], CAMERA_POSITION[2])
theta = Point(CAMERA_ROTATION[0], CAMERA_ROTATION[1], CAMERA_ROTATION[2])
d = Point()
e = Point(0, 0, CAMERA_POSITION[2] + SENSOR_OFFSET)
costx = cos(theta.x)
costy = cos(theta.y)
costz = cos(theta.z)
sintx = sin(theta.x)
sinty = sin(theta.y)
sintz = sin(theta.z)
for x in xrange(cv.GetSize(image)[0]):
for y in xrange(cv.GetSize(image)[1]):
a = Point(x, y, heights_top[x/2] * (cv.GetSize(image)[1] - y) + heights_bottom[x/2] * y)
b = Point()
d.x = costy * (sintz * (a.y - c.y) + costz * (a.x - c.x)) - sinty * (a.z - c.z)
d.y = sintx * (costy * (a.z - c.z) + sinty * (sintz * (a.y - c.y) + costz * (a.x - c.x))) + costx * (costz * (a.y - c.y) - sintz * (a.x - c.x))
d.z = costx * (costy * (a.z - c.z) + sinty * (sintz * (a.y - c.y) + costz * (a.x - c.x))) - sintx * (costz * (a.y - c.y) - sintz * (a.x - c.x))
mapX[y, x] = x + (d.x - e.x) * (e.z/d.z)
mapY[y, x] = y + (d.y - e.y) * (e.z/d.z)
print
print 'Remapping original image using map...'
remapped = cv.CreateImage(cv.GetSize(image), 8, 3)
cv.Remap(image, remapped, mapX, mapY, cv.CV_INTER_LINEAR)
ta zamienia się w ogromną wątku obrazów i kodu teraz ... W każdym razie, ten fragment kodu zajmuje moje 7 minut, aby uruchomić na obrazie z kamery 18MP; to zbyt długo, a na koniec to podejście nie robi nic dla obrazu (przesunięcie dla każdego piksela to << 1
).
Wszelkie pomysły?
Can OpenCV map 3D do 2D ? Czy muszę wymyślić własną formułę? Spróbuję to jednak wdrożyć, dzięki! – Blender