2013-09-30 27 views
1

Мне нужно вычислить матрицу деформаций в OpenCV, представляющую поворот вокруг данной оси.Повернуть изображение вокруг оси x, y, z в OpenCV

вокруг оси Z -> проста: я использую стандартную матрицу вращения

[cos(a) -sin(a) 0] 
[sin(a) cos(a) 0] 
[ 0  0 1] 

Это не столь очевидно для других поворотов, так что я пытался строить гомография, как описано в Википедии:

H = R - t n^T/d 

Я пробовал с простым вращением вокруг оси X, и предполагая, что расстояние между камерой и изображением вдвое превышает высоту изображения.

R является стандартной матрицей вращения

[1  0  0] 
[0 cos(a) -sin(a)] 
[0 sin(a) cos(a)] 

п [0 0 1], потому что камера смотрит прямо на изображении, из (0, 0, z_cam)

т является переводом, который должен быть [0 -2h*(sin(a)) -2h*(1-cos(a))]

d - расстояние, и оно составляет 2 часа за определение.

Таким образом, окончательная матрица:

[1  0 0] 
[0 cos(a) 0] 
[0 sin(a) 1] 

, который выглядит довольно хорошо, когда а = 0 это тождество, а при а = р это отражается вокруг оси х.

И все же, использование этой матрицы для перспективной деформации не дает ожидаемого результата, изображение просто «слишком искажено» для небольших значений a и очень быстро исчезает.

Итак, что я делаю неправильно?

(примечание: Я прочитал много вопросов и ответов на эту тему, но все они идут в противоположном направлении: Я не хочу, чтобы разлагаются матрицу гомография, а скорее построить один, учитывая трехмерное преобразование и «фиксированная» камера или фиксированное изображение и движущаяся камера).

спасибо.

+0

Как вы установили свою систему координат? – Michele

+0

(0,0) - верхний левый, x = colum, y = row. В принципе, изображение загружается с использованием cv :: imread, и никаких преобразований не применяется. –

+0

Я думаю, вы должны использовать представление по оси, а затем экспоненциальную карту, чтобы получить свою матрицу вращения [см. Эту ссылку для краткого объяснения] (http://en.wikipedia.org/wiki/Axis%E2%80%93angle_representation) – Michele

ответ

4

Наконец нашел способ, благодаря этому сообщению: https://plus.google.com/103190342755104432973/posts/NoXQtYQThgQ

Я позволил OpenCV вычислить матрицу для меня, но я делаю перспективное преобразование себя (было легче реализовать, чем положить все в резюме: : Mat)

float rotx, roty, rotz; // set these first 
int f = 2; // this is also configurable, f=2 should be about 50mm focal length 

int h = img.rows; 
int w = img.cols; 

float cx = cosf(rotx), sx = sinf(rotx); 
float cy = cosf(roty), sy = sinf(roty); 
float cz = cosf(rotz), sz = sinf(rotz); 

float roto[3][2] = { // last column not needed, our vector has z=0 
    { cz * cy, cz * sy * sx - sz * cx }, 
    { sz * cy, sz * sy * sx + cz * cx }, 
    { -sy, cy * sx } 
}; 

float pt[4][2] = {{ -w/2, -h/2 }, { w/2, -h/2 }, { w/2, h/2 }, { -w/2, h/2 }}; 
float ptt[4][2]; 
for (int i = 0; i < 4; i++) { 
    float pz = pt[i][0] * roto[2][0] + pt[i][1] * roto[2][1]; 
    ptt[i][0] = w/2 + (pt[i][0] * roto[0][0] + pt[i][1] * roto[0][1]) * f * h/(f * h + pz); 
    ptt[i][1] = h/2 + (pt[i][0] * roto[1][0] + pt[i][1] * roto[1][1]) * f * h/(f * h + pz); 
} 

cv::Mat in_pt = (cv::Mat_<float>(4, 2) << 0, 0, w, 0, w, h, 0, h); 
cv::Mat out_pt = (cv::Mat_<float>(4, 2) << ptt[0][0], ptt[0][1], 
    ptt[1][0], ptt[1][1], ptt[2][0], ptt[2][1], ptt[3][0], ptt[3][1]); 

cv::Mat transform = cv::getPerspectiveTransform(in_pt, out_pt); 

cv::Mat img_in = img.clone(); 
cv::warpPerspective(img_in, img, transform, img_in.size()); 
Смежные вопросы