Ho una mappa di altezza per un'immagine, che indica l'offset di ciascun pixel nella direzione Z. Il mio obiettivo è appiattire un'immagine distorta usando solo la sua mappa di altezza.Distorsione di un'immagine utilizzando una mappa di altezza?
Come faccio a fare questo? Conosco la posizione della telecamera, se questo aiuta.
Per fare questo, pensavo supponendo che ciascun pixel è un punto su un piano, e quindi di tradurre ciascuno di questi punti verticalmente secondo il valore Z ottengo dalla mappa altezza, e da quella traduzione (immagina di guardare i punti dall'alto, lo spostamento farà sì che il punto si muova dalla tua prospettiva).
Da tale spostamento previsto, è stato possibile estrarre lo spostamento X e Y di ciascun pixel, che potrei inserire in cv.Remap()
.
Ma non ho idea di come sia possibile ottenere l'offset 3D proiettato di un punto con OpenCV, per non parlare di costruire una mappa sfalsata.
Qui sono le mie immagini di riferimento per quello che sto facendo:
So che l'angolo dei laser (45 gradi), e dalle immagini di calibrazione, posso calcolare l'altezza del libro molto facilmente:
h(x) = sin(theta) * abs(calibration(x) - actual(x))
Faccio questo per entrambe le linee e interpolare linearmente le due lin es per generare una superficie usando questo approccio (codice Python. E 'all'interno di un ciclo):
height_grid[x][y] = heights_top[x] * (cv.GetSize(image)[1] - y) + heights_bottom[x] * y
Spero che questo aiuta;)
In questo momento, questo è quello che ho da dewarp l'immagine. Tutta quella roba strana nei progetti di mezzo di coordinate 3D sul piano della macchina fotografica, data la sua posizione (e la posizione della fotocamera, la rotazione, ecc):
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)
Questo si sta trasformando in un enorme filo di immagini e il codice ora ... Comunque, questo pezzo di codice impiega i miei 7 minuti per girare su un'immagine da 18MP; questo è modo troppo lungo e, alla fine, questo approccio non fa nulla all'immagine (l'offset per ogni pixel è << 1
).
Qualche idea?
Can OpenCV mappa 3D in 2D ? O devo venire con la mia formula per questo? Cercherò di implementare questo, però, quindi grazie! – Blender