주요 콘텐츠

자동으로 영상 회전과 스케일 구하기

이 예제에서는 두 영상 간의 기하 변환을 자동으로 확인하는 방법을 보여줍니다. 특히 한 영상이 회전과 스케일링 때문에 다른 영상에 비해 왜곡된 경우 함수 detectSURFFeaturesestimateGeometricTransform2D를 사용하여 회전 각도와 스케일링 인자를 식별할 수 있습니다. 그런 다음 이러한 파라미터를 사용하여 왜곡된 영상을 원래 모습으로 다시 변환할 수 있습니다.

영상 읽어 들이기

영상을 작업 공간으로 불러옵니다.

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");

영상의 크기를 조정하고 회전하기

스케일링 인자를 변경합니다.

scale = 0.7;
J = imresize(original,scale);

% Adjust the rotation angle, |theta|. The function |imrotate| rotates images
% counterclockwise for positive values of |theta|. To rotate the image
% clockwise, use a negative value for |theta|.
theta = 30;
distorted = imrotate(J,-theta);
figure
imshow(distorted)

입력 영상의 다양한 스케일과 회전으로 실험해 보면 더 나은 결과를 얻을 수 있습니다. 그러나 스케일에 지나치게 큰 변화를 주면, 특징 검출기가 특징을 충분히 인식하지 못하여 정확한 분석을 못할 수 있습니다.

영상 간에 매칭되는 특징 찾기

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

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)");

변환 추정하기

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");

스케일과 각도 구하기

기하 변환 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"

복구된 값은 영상 크기 조정 및 회전 과정에서 선택한 스케일 및 각도 값과 일치해야 합니다. 또한, 스케일과 회전 각도는 simtform2d 객체의 스케일 및 회전 각도 속성에서도 확인할 수 있습니다.

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

    "RotationAngle: "    "29.3451"

원래 영상 복구하기

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

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

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

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

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