Main Content

자동화된 특징 매칭을 사용하여 영상 회전과 스케일 구하기

이 예제에서는 단일 영상 쌍 간의 기하 변환을 자동으로 확인하는 방법을 보여줍니다. 한 영상이 회전과 스케일 때문에 다른 영상보다 왜곡된 경우 detectSURFFeaturesestgeotform2d를 사용하여 회전 각도와 스케일링 인자를 찾을 수 있습니다. 그런 다음 왜곡된 영상을 변환하여 원래 영상을 복구할 수 있습니다.

1단계: 영상 읽어 들이기

영상을 작업 공간으로 가져옵니다.

original = imread('cameraman.tif');
imshow(original);
text(size(original,2),size(original,1)+15, ...
    'Image courtesy of Massachusetts Institute of Technology', ...
    FontSize=7,HorizontalAlignment='right');

2단계: 영상의 크기를 조정하고 회전하기

scale = 0.7;
J = imresize(original,scale); % Try varying the scale factor.

theta = 30;
% Note that imrotate rotates images in a counterclockwise direction when
% you specify a positive angle of rotation. To rotate the image clockwise,
% specify a negative theta.
distorted = imrotate(J,-theta); % Try varying the angle, theta.
figure
imshow(distorted)

입력 영상의 스케일과 회전을 변화시키면서 실험해 볼 수 있습니다. 그러나 특징 검출기가 충분한 특징을 찾는 데 실패하기 전까지 변화를 줄 수 있는 스케일의 양에는 한계가 있습니다.

3단계: 영상 간에 매칭되는 특징 찾기

두 영상에서 특징을 검출합니다.

ptsOriginal = detectSURFFeatures(original);
ptsDistorted = detectSURFFeatures(distorted);

특징 설명자를 추출합니다.

[featuresOriginal,validPtsOriginal] = extractFeatures(original,ptsOriginal);
[featuresDistorted,validPtsDistorted] = extractFeatures(distorted,ptsDistorted);

설명자를 사용하여 특징을 매칭시킵니다.

indexPairs = matchFeatures(featuresOriginal,featuresDistorted);

각 영상에 대응하는 점의 위치를 가져옵니다.

matchedOriginal = validPtsOriginal(indexPairs(:,1));
matchedDistorted = validPtsDistorted(indexPairs(:,2));

매칭되는 추정점을 표시합니다.

figure
showMatchedFeatures(original,distorted,matchedOriginal,matchedDistorted);
title('Putatively matched points (including outliers)');

4단계: 변환 추정하기

통계적으로 강건하면서 RANSAC 알고리즘의 변형인 MSAC(M-estimator SAmple Consensus) 알고리즘을 사용하여 매칭 점 쌍에 대응하는 변환을 찾습니다. 여기서는 변환 행렬을 계산하는 동안 이상값을 제거합니다. MSAC 알고리즘에서 사용하는 무작위 샘플링 때문에 다양한 변환 계산 결과가 나올 수 있습니다.

[tform, inlierIdx] = estgeotform2d(matchedDistorted,matchedOriginal,'similarity');
inlierDistorted = matchedDistorted(inlierIdx,:);
inlierOriginal = matchedOriginal(inlierIdx,:);

변환 계산에 사용된 매칭 점 쌍을 표시합니다.

figure;
showMatchedFeatures(original,distorted,inlierOriginal,inlierDistorted);
title('Matching points (inliers only)');
legend('ptsOriginal','ptsDistorted');

5단계: 스케일과 각도 구하기

기하 변환 tform을 사용하여 스케일과 각도를 복구합니다. 왜곡된 영상에서 원래 영상으로의 변환을 계산했기 때문에 그 역변환을 계산하여 왜곡을 복구해야 합니다.

Let sc = s*cos(theta)
Let ss = s*sin(theta)
Then, Ainv = [sc  ss  tx;
             -ss  sc  ty;
               0   0   1]
where tx and ty are x and y translations, respectively.

역변환 행렬을 계산합니다.

invTform = invert(tform);
Ainv = invTform.A;

ss = Ainv(1,2);
sc = Ainv(1,1);
scaleRecovered = hypot(ss,sc);
disp(['Recovered scale: ', num2str(scaleRecovered)])

% Recover the rotation in which a positive value represents a rotation in
% the clockwise direction.
thetaRecovered = atan2d(-ss,sc);
disp(['Recovered theta: ', num2str(thetaRecovered)])
Recovered scale: 0.70126
Recovered theta: 29.3451

복구된 값은 2단계: 영상의 크기를 조정하고 회전하기에서 선택한 스케일 및 각도 값과 일치해야 합니다.

스케일과 회전 각도는 simtform2d 객체의 Scale 및 RotationAngle 속성에서도 확인할 수 있습니다.

disp(['Scale: ' num2str(invTform.Scale)])
disp(['RotationAngle: ' num2str(invTform.RotationAngle)])
Scale: 0.70126
RotationAngle: 29.3451

6단계: 원래 영상 복구하기

왜곡된 영상을 변환하여 원래 영상을 복구합니다.

outputView = imref2d(size(original));
recovered = imwarp(distorted,tform,OutputView=outputView);

recoveredoriginal을 몽타주에 나란히 놓고 비교합니다.

figure, imshowpair(original,recovered,'montage')

왜곡과 복구 과정 때문에 recovered(오른쪽) 영상 품질이 original(왼쪽) 영상과 일치하지 않습니다. 특히, 영상 축소는 정보 손실의 원인이 됩니다. 가장자리 주변의 아티팩트는 변환의 제한된 정확도로 인해 발생합니다. 3단계: 영상 간에 매칭되는 특징 찾기에서 더 많은 점을 검출했다면 변환이 더 정확했을 것입니다. 예를 들어 코너 검출기 detectFASTFeatures를 사용하여 블롭을 찾는 SURF 특징 검출기를 보완할 수 있습니다. 영상 콘텐츠와 영상 크기도 검출되는 특징 수에 영향을 미칩니다.