У меня есть карта высот для изображения, которая показывает мне смещение каждого пикселя в направлении Z. Моя цель - сгладить искаженное изображение, используя только его карту высот.
Как бы я поступил так? Я знаю положение камеры, если это поможет.
Чтобы сделать это, я думал о том, чтобы предположить, что каждый пиксель был точкой на плоскости, а затем перевести каждую из этих точек по вертикали в соответствии со значением Z, полученным из карты высот и из этого перевода (представьте себе, вы смотрите на точки сверху, сдвиг заставит точку двигаться с вашей точки зрения).
Из этого спроецированного сдвига я мог извлечь X и Y-сдвиг каждого пикселя, которые я мог бы передать в cv.Remap()
.
Но я понятия не имею, как можно получить проецируемое трехмерное смещение точки с помощью OpenCV, не говоря уже о том, чтобы из нее построить карту смещения.
Вот мои справочные изображения для того, что я делаю:
Я знаю угол наклона лазеров (45 градусов), и по калибровочным изображениям я могу очень легко рассчитать высоту книги:
h(x) = sin(theta) * abs(calibration(x) - actual(x))
Я делаю это для обеих линий и линейно интерполирую две линии для генерации поверхности, используя этот подход (код Python. Он находится внутри цикла):
height_grid[x][y] = heights_top[x] * (cv.GetSize(image)[1] - y) + heights_bottom[x] * y
Надеюсь, это поможет;)
Прямо сейчас, это то, что мне нужно, чтобы выровнять изображение. Все эти странные вещи в центре проецируют трехмерную координату на плоскость камеры, учитывая ее положение (и местоположение камеры, вращение и т. Д.):
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)
Теперь это превращается в огромный поток изображений и кода ... В любом случае, этот фрагмент кода занимает у меня 7 минут, чтобы запустить изображение с 18-мегапиксельной камеры; это путь слишком длинный, и, в конце концов, этот подход ничего не делает с изображением (смещение для каждого пикселя составляет << 1
).
Есть идеи?