画像の高さマップがあり、Z方向の各ピクセルのオフセットがわかります。私の目標は、高さマップのみを使用して、歪んだ画像を平坦化することです。
どうすればこれを行うことができますか?それが助けになるなら、私はカメラの位置を知っています。
これを行うには、各ピクセルが平面上の点であると想定し、高さマップとその変換から取得したZ値に従って、これらの各点を垂直方向に変換することを考えていました(あなたが見ていると想像してください)上からのポイントで;シフトにより、ポイントがあなたの視点から動き回ります)。
その投影されたシフトから、各ピクセルのXシフトとYシフトを抽出でき、これをにフィードできますcv.Remap()
。
しかし、OpenCVを使用してポイントの投影された3Dオフセットを取得する方法、ましてやそれからオフセットマップを作成する方法がわかりません。
これが私がしていることの私の参照画像です:
私はレーザーの角度(45度)を知っており、キャリブレーション画像から、本の高さを非常に簡単に計算できます。
h(x) = sin(theta) * abs(calibration(x) - actual(x))
私は両方のラインに対してこれを行い、このアプローチを使用して2つのラインを線形補間し、サーフェスを生成します(Pythonコード。ループ内にあります)。
height_grid[x][y] = heights_top[x] * (cv.GetSize(image)[1] - y) + heights_bottom[x] * y
これがお役に立てば幸いです;)
今、これは私が画像をデワープしなければならないものです。真ん中の奇妙なものはすべて、カメラの位置(およびカメラの位置、回転など)を指定して、3D座標をカメラ平面に投影します。
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)
これは今、画像とコードの巨大なスレッドに変わりつつあります...とにかく、このコードチャンクは18MPカメラ画像で実行するのに7分かかります。これは長すぎます。最終的に、このアプローチは画像に何の影響も与えません(各ピクセルのオフセットはです)<< 1
。
何か案は?