Деформация изображения с использованием крена, тангажа и рыскания
В настоящее время я использую OpenCV в Python, чтобы исправить искажения изображения в аэрофотоснимке. У меня есть данные для крена, тангажа и рыскания. Я понимаю, что мне нужно создать матрицу деформации и применить матрицу к моим исходным координатным точкам, чтобы создать выходные точки для изображения. Я могу влиять на то, как изображение движется, но я чувствую, что есть ошибка, потому что единственные значения, которые, кажется, работают для очень маленьких значений.
Вот мой текущий код:
warp_mat = np.array([[math.cos(theta)*math.cos(psy), math.cos(phi)*math.sin(psy)+math.sin(phi)*math.sin(theta)*math.cos(psy), math.sin(phi)*math.sin(psy)-math.cos(phi)*math.sin(theta)*math.cos(psy)],\
[-1*math.cos(theta)*math.sin(psy), math.cos(phi)*math.cos(psy)-math.sin(phi)*math.sin(theta)*math.sin(psy), math.sin(phi)*math.cos(psy)+math.cos(phi)*math.sin(theta)*math.sin(psy)],\
[math.sin(theta), -1*math.sin(phi)*math.cos(theta), math.cos(phi)*math.cos(theta)]], dtype='float32')
srcPts = np.array([[-2064, 1161, 1],\
[2064, 1161, 1],\
[2064, -1161, 1],\
[-2064, -1161, 1]], dtype='float32')
dstPts = np.empty(shape = (4,3), dtype='float32')
dstPts[0][0] = srcPts[0][0] * warp_mat[0][0] + srcPts[0][1] * warp_mat[1][0] + srcPts[0][2] * warp_mat[2][0];
dstPts[0][1] = srcPts[0][0] * warp_mat[0][1] + srcPts[0][1] * warp_mat[1][1] + srcPts[0][2] * warp_mat[2][1];
dstPts[0][2] = srcPts[0][0] * warp_mat[0][2] + srcPts[0][1] * warp_mat[1][2] + srcPts[0][2] * warp_mat[2][2];
dstPts[1][0] = srcPts[1][0] * warp_mat[0][0] + srcPts[1][1] * warp_mat[1][0] + srcPts[1][2] * warp_mat[2][0];
dstPts[1][1] = srcPts[1][0] * warp_mat[0][1] + srcPts[1][1] * warp_mat[1][1] + srcPts[1][2] * warp_mat[2][1];
dstPts[1][2] = srcPts[1][0] * warp_mat[0][2] + srcPts[1][1] * warp_mat[1][2] + srcPts[1][2] * warp_mat[2][2];
dstPts[2][0] = srcPts[2][0] * warp_mat[0][0] + srcPts[2][1] * warp_mat[1][0] + srcPts[2][2] * warp_mat[2][0];
dstPts[2][1] = srcPts[2][0] * warp_mat[0][1] + srcPts[2][1] * warp_mat[1][1] + srcPts[2][2] * warp_mat[2][1];
dstPts[2][2] = srcPts[2][0] * warp_mat[0][2] + srcPts[2][1] * warp_mat[1][2] + srcPts[2][2] * warp_mat[2][2];
dstPts[3][0] = srcPts[3][0] * warp_mat[0][0] + srcPts[3][1] * warp_mat[1][0] + srcPts[3][2] * warp_mat[2][0];
dstPts[3][1] = srcPts[3][0] * warp_mat[0][1] + srcPts[3][1] * warp_mat[1][1] + srcPts[3][2] * warp_mat[2][1];
dstPts[3][2] = srcPts[3][0] * warp_mat[0][2] + srcPts[3][1] * warp_mat[1][2] + srcPts[3][2] * warp_mat[2][2];
dstPts[0][0] = dstPts[0][0] / dstPts[0][2];
dstPts[0][1] = dstPts[0][1] / dstPts[0][2];
dstPts[0][2] = dstPts[0][2] / dstPts[0][2];
dstPts[1][0] = dstPts[1][0] / dstPts[1][2];
dstPts[1][1] = dstPts[1][1] / dstPts[1][2];
dstPts[1][2] = dstPts[1][2] / dstPts[1][2];
dstPts[2][0] = dstPts[2][0] / dstPts[2][2];
dstPts[2][1] = dstPts[2][1] / dstPts[2][2];
dstPts[2][2] = dstPts[2][2] / dstPts[2][2];
dstPts[3][0] = dstPts[3][0] / dstPts[3][2];
dstPts[3][1] = dstPts[3][1] / dstPts[3][2];
dstPts[3][2] = dstPts[3][2] / dstPts[3][2];
srcPts2 = np.array([[srcPts[0][0],srcPts[0][1]],\
[srcPts[1][0],srcPts[1][1]],\
[srcPts[2][0],srcPts[2][1]],\
[srcPts[3][0],srcPts[3][1]]], dtype='float32')
dstPts2 = np.array([[dstPts[0][0],dstPts[0][1]],\
[dstPts[1][0],dstPts[1][1]],\
[dstPts[2][0],dstPts[2][1]],\
[dstPts[3][0],dstPts[3][1]]], dtype='float32')
transMatrix = cv.getPerspectiveTransform(srcPts2, dstPts2)
dst = cv.warpPerspective(imgFile,transMatrix,(4128,2322) ,borderMode = cv.BORDER_CONSTANT,borderValue = 0)
2 ответа
Код BirdsEyeView() работает для меня, но я не знаю, почему меняются углы крена и тангажа. Когда я изменяю "альфа", изображение деформируется по высоте, а когда я меняю "бета", изображение деформируется в рулоне. Итак, я изменил свою матрицу вращения, как можно видеть ниже.
Также RY имеет ошибку сигнала. Вы можете проверить Ry по адресу: http://en.wikipedia.org/wiki/Rotation_matrix Я думаю, именно поэтому Адриан изменил порядок умножения с R = RX * RY * RZ на R = RZ * RX * RY.
Метрика вращения, которую я использую:
Mat RX = (Mat_<double>(4, 4) <<
1, 0, 0, 0,
0, cos(beta), -sin(beta), 0,
0, sin(beta), cos(beta), 0,
0, 0, 0, 1);
Mat RY = (Mat_<double>(4, 4) <<
cos(alpha), 0, sin(alpha), 0,
0, 1, 0, 0,
-sin(alpha), 0, cos(alpha), 0,
0, 0, 0, 1);
Mat RZ = (Mat_<double>(4, 4) <<
cos(gamma), -sin(gamma), 0, 0,
sin(gamma), cos(gamma), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1);
С уважением
В начале вашего кода вы вычисляете матрицу деформации, проецируя четыре точки, а затем используете getPerspectiveTransform(), чтобы найти матрицу преобразования. Это должно работать, но это сложнее, чем необходимо. Если вам известны углы крена, тангажа и рыскания, вы можете напрямую рассчитать матрицу преобразования. Посмотрите на функцию BirdsEyeView() в http://image2measure.net/files/calib3Dto2D.cpp. Это именно так.
Я должен был изменить линию Mat R = RX * RY * RZ;
вMat R = RZ * RX * RY;
для того, чтобы получить правильное преобразование.
f - фокусное расстояние в пикселях.
Если rh - горизонтальное разрешение вашего изображения и ой горизонтальный угол раскрытия камеры
f = (rh/2)/tan(oh/2)
Выберите то же значение для расстояния, если вы не хотите масштабировать изображение, большее, чем f, чтобы увеличить его, или меньшее, чтобы уменьшить его.