2013-08-20 2 views
5

3D 변형 행렬을 사용하여 이미지를 변형하려고하고 있으며 카메라가 정규직이라고 가정합니다.호모 그래 픽 이미지 변형 왜곡 문제

I 13.

하틀리 및 Zisserman 장에서 제시된 I 누군지 (Inf를 너무 H = R = D로)면 유도 된 호모 그래피 화학식 H =있는 걸 * n을 '/ D를 사용하여 내 호모 그래피를 형성하고 혼란스러운 점은 다소 겸손한 회전을 사용할 때 이미지가 예상보다 훨씬 왜곡 된 것처럼 보입니다 (나는 라디안과 각도를 혼동하지 않는다고 확신합니다).

무엇이 잘못 될 수 있습니까?

필자는 코드와 예제 출력을 첨부했습니다.

Example Output

n = [0;0;-1]; 
d = Inf; 

im = imread('cameraman.tif'); 

rotations = [0 0.01 0.1 1 10]; 

for ind = 1:length(rotations) 
     theta = rotations(ind)*pi/180; 

     R = [ 1  0   0 ; 
      0 cos(theta) -sin(theta); 
      0 sin(theta) cos(theta)]; 

     t = [0;0;0]; 

     H = R-t*n'/d; 

     tform = maketform('projective',H'); 
     imT = imtransform(im,tform); 

     subplot(1,5,ind) ; 
     imshow(imT) 
     title(['Rot=' num2str(rotations(ind)) 'deg']); 
     axis square 
end 
+0

내 대답 도움이 경우에 당신은 대답으로 표시 줄래 :

enter image description here

새로운 설정은? 감사. – Frederick

+0

@klurie'imagehomog' 함수를 사용하여 결과를 얻었습니까? –

답변

5

D이 경우에 충족되지 않는 하나 개의 가정을 가지고/수식 H =있는 걸 * n을 '

이 수식은 핀홀 카메라 모델을 사용하는 것을 의미 초점 길이 = 1 인 경우

그러나 귀하의 경우 카메라가 더 현실적이고 코드가 작동하려면 초점 거리를 몇 가지로 설정해야합니다 (초점 거리는 카메라 중심에서 이미지 평면까지의 거리입니다.)

이렇게하려면 초점 길이를 처리하는 교정 매트릭스 K를 정의 할 수 있습니다. 수식을 으로 변경하면됩니다. H = KR inv (K) - 1/d Ktn 'inv (K) 여기서 K는 대각선을 따라 두 개의 첫 번째 요소가있는 3x3 단위 행렬입니다. 초점 거리 (예 : f = 300)로 설정하십시오. 수식은 투영 카메라를 가정하면 쉽게 파생 될 수 있습니다.

아래는 코드가 수정 된 것으로서 각도가 맞습니다.

n = [0;0;-1]; 
d = Inf; 

im = imread('cameraman.tif'); 

rotations = [0 0.01 0.1 30 60]; 

for ind = 1:length(rotations) 
    theta = rotations(ind)*pi/180; 

    R = [ 1  0   0 ; 
     0 cos(theta) -sin(theta); 
     0 sin(theta) cos(theta)]; 

    t = [0;0;0]; 

    K=[300 0 0; 
     0 300 0; 
     0 0 1]; 

    H=K*R/K-1/d*K*t*n'/K; 

    tform = maketform('projective',H'); 
    imT = imtransform(im,tform); 

    subplot(1,5,ind) ; 
    imshow(imT) 
    title(['Rot=' num2str(rotations(ind)) 'deg']); 
    axis square 
end 

당신은 아래 이미지에서 결과를 볼 수 있습니다

당신은 또한 센터 주변의 이미지를 회전 할 수 있습니다. 그것은 당신이 이미지 평면의 기원을 내가 matlab (maketform)의 그 방법으로는 불가능하다고 생각하는 이미지의 중심으로 설정해야합니다. 대신 아래 방법을 사용할 수 있습니다.

imT=imagehomog(im,H','c'); 

이 방법을 사용하는 경우 적절한 결과를 얻으려면 n, d, t 및 R의 일부 설정을 변경해야합니다. 해당 방법은 다음에서 찾을 수 있습니다. https://github.com/covarep/covarep/blob/master/external/voicebox/imagehomog.m

imagehomog가있는 프로그램의 결과와 n, d, t 및 R의 일부 변경 내용이 아래에 표시되어 있습니다. ,

n = [0 0 1]'; 
d = 2; 
t = [1 0 0]'; 
R = [cos(theta), 0, sin(theta); 
    0,   1,   0; 
    -sin(theta), 0, cos(theta)]; 
+0

'imagehomog '를 사용하여 보여준 이미지는 60도 회전이됩니까? –

+1

저는 60 도의 값을 가진'H'를 사용했습니다. 하지만이 이미지가 아니라 출력에 작은 상자를 보여줍니다. –

+1

@AadnanFarooqA, 나는 편집하여 적절한 결과를 얻기 위해 imagehomog와 함께 사용할 수 있도록 답변을 수정했습니다. –

1

당신은 X 주위에 회전을시킴으로써 행한다 수행 : 당신의 매트릭스, 제 1 구성 요소 (X)는 회전 행렬에 의해 변경되지 않습니다. 이는 예제의 perspective 변형에 의해 확인됩니다.

변형의 실제 양은 카메라와 이미지 평면 사이의 거리에 따라 달라집니다 (또는 카메라의 초점 거리에 대한 값에 더 정확하게). 카메라 맨 이미지 평면이 카메라 근처에있을 때 중요 할 수 있습니다.

4

음 ... 나는이 물건에 100 % 퍼센트가 아니지만 흥미로운 질문이었고 내 작업과 관련이있어서 나는 놀아서 한 발을 내줄 것이라고 생각했습니다.

EDIT :이 기능은 내장형을 사용하지 않고 한 번 사용해 보았습니다. 그것은 나의 원래 대답이었다.

귀하의 질문에 쉽게 대답은 z 축에 대한 올바른 회전 행렬을 사용하는 것입니다 : 그럼 난 당신이 아주 쉽게 그것을 당신의 방법을 할 수있는 것을 깨달았다 여기

R = [cos(theta) -sin(theta) 0; 
    sin(theta) cos(theta) 0; 
    0    0   1]; 

하는 또 다른 방법 그것을하십시오 (나의 원래 응답) :

나는 나가 한 무슨을 나 공유하기 위하여려고하고있다; 잘하면 이것은 당신에게 유용합니다. 나는 2D로만 만들었지 만 3D로 확장하기는 쉽습니다. 평면에서 이미지를 회전하려면 현재 코딩 한 다른 회전 행렬을 사용해야합니다. Z 축에 대해 회전해야합니다.
나는 matlab 내장 함수를 사용하지 않았다.

일부 정보는 http://en.wikipedia.org/wiki/Rotation_matrix입니다.

im = double(imread('cameraman.tif')); % must be double for interpn 

[x y] = ndgrid(1:size(im,1), 1:size(im,2)); 

rotation = 10; 
theta = rotation*pi/180; 

% calculate rotation matrix 
R = [ cos(theta) -sin(theta); 
    sin(theta) cos(theta)]; % just 2D case 

% calculate new positions of image indicies 

tmp = R*[x(:)' ; y(:)']; % 2 by numel(im) 
xi = reshape(tmp(1,:),size(x)); % new x-indicies 
yi = reshape(tmp(2,:),size(y)); % new y-indicies 

imrot = interpn(x,y,im,xi,yi); % interpolate from old->new indicies 

imagesc(imrot); 

rotation image

내 자신의 문제는 지금 : "어떻게 내가 (0,0), 왼쪽 상단 중심으로 회전하고있어, 분명히 이미지를 회전하는에 대한 원점을 변경합니까? .

편집 아스 커의 의견에 대응하여 2, 나는 다시 시도했습니다.
나는 몇 가지 고정이 시간을.이제 원래의 질문에서와 같은 변형 행렬 (x에 대해)을 사용하고 있습니다.
이미지의 중심에 ndgrid (0,0,0 지정)을 반복하는 방식으로 이미지의 중심을 중심으로 회전했습니다. 나는 또한 이미지의 3면을 보여 주기로 결정했다. 이것은 원래의 질문에 있지 않았습니다. 중간면은 관심 비행기입니다. 중간 평면을 얻으려면 제로 패딩을 생략하고 -1:1 대신 1이되도록 ndgrid 세 번째 옵션을 다시 정의하면됩니다.

im = double(imread('cameraman.tif')); % must be double for interpn 
im = padarray(im, [0 0 1],'both'); 

[x y z] = ndgrid(-floor(size(im,1)/2):floor(size(im,1)/2)-1, ... 
    -floor(size(im,2)/2):floor(size(im,2)/2)-1,... 
    -1:1); 

rotation = 1; 
theta = rotation*pi/180; 

% calculate rotation matrix 
R = [ 1  0   0 ; 
     0 cos(theta) -sin(theta); 
     0 sin(theta) cos(theta)]; 

% calculate new positions of image indicies 
tmp = R*[x(:)'; y(:)'; z(:)']; % 2 by numel(im) 

xi = reshape(tmp(1,:),size(x)); % new x-indicies 
yi = reshape(tmp(2,:),size(y)); % new y-indicies 
zi = reshape(tmp(3,:),size(z)); 

imrot = interpn(x,y,z,im,xi,yi,zi); % interpolate from old->new indicies 

figure; 
subplot(3,1,1);imagesc(imrot(:,:,1)); axis image; axis off; 
subplot(3,1,2);imagesc(imrot(:,:,2)); axis image; axis off; 
subplot(3,1,3);imagesc(imrot(:,:,3)); axis image; axis off; 

new version

+1

이미지를 원점'(rx, ry)'주위로 회전하려면,'(-rx, -ry)'로 번역하고, 회전시킨 다음'(rx, ry)'를 역으로 변환하십시오. 이 단계는 개별적으로 적용 할 수도 있고 행렬을 미리 곱할 수도 있습니다. – lnmx

+0

시간을내어 주셔서 감사합니다, 프레드릭. 내 목표는 z 축을 중심으로 회전하지 않는 것입니다. x 축 (또는 y 축)을 중심으로 회전하면 이미지가 페이지 평면 밖으로 나오게됩니다. – klurie