상위 목록: 하위 목록: 작성 날짜: 읽는 데 14 분 소요

아핀 변환(Affine Transformation)

아핀 변환(Affine Transformation)선형 변환이동 변환까지 포함된 변환입니다.

선의 수평성을 유지하며, 변환 전의 서로 평행한 선은 변환 후에도 평행함을 의미합니다.

즉, 길이의 비평행성보존되는 변환입니다. 사각형을 평행사변형으로 변환하는 것을 아핀 변환으로 간주합니다.



아핀 변환 행렬(Affine Transformation Matrix)

아핀 변환 행렬의 기본형은 3×3 행렬이지만 세 번째 행의 값은 0, 0, 1의 값을 지닙니다.

좌변의 행렬과 우변의 행렬의 세 번째 행의 값은 항상 같은 값을 지니게 되어 OpenCV에서는 2×3 행렬로 표현합니다.

행렬의 \(x_1\), \(y_1\)은 변환 전 원본 이미지의 픽셀 좌표를 의미하며, \(x_2\), \(y_2\)는 변환 후의 결과 이미지의 픽셀 좌표를 의미합니다.

변환 후의 픽셀 좌표를 계산하기 위해서는 미지수 \(a_{00}\), \(a_{01}\), \(a_{10}\), \(a_{11}\), \(b_0\), \(b_1\)의 값을 알아야 합니다.

여섯 개의 미지수를 구하기 위해 세 개의 좌표를 활용해 미지수를 계산합니다.



메인 코드

using System;
using OpenCvSharp;
using System.Collections.Generic;

namespace Project
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = new Mat("snow.jpg");
            Mat dst = new Mat();

            List<Point2f> src_pts = new List<Point2f>()
            {
                new Point2f(0.0f, 0.0f),
                new Point2f(0.0f, src.Height),
                new Point2f(src.Width, src.Height)
            };

            List<Point2f> dst_pts = new List<Point2f>()
            {
               new Point2f(300.0f, 300.0f),
               new Point2f(300.0f, src.Height),
               new Point2f(src.Width - 400.0f, src.Height - 200.0f)
            };

            Mat matrix = Cv2.GetAffineTransform(src_pts, dst_pts);
            Cv2.WarpAffine(src, dst, matrix, new Size(src.Width, src.Height));

            Cv2.ImShow("dst", dst);
            Cv2.WaitKey(0);
        }   
    }
}


세부 코드

Mat src = new Mat("snow.jpg");
Mat dst = new Mat();

new Mat을 사용해 이미지를 src에 할당합니다.

연산 결과를 저장할 dst를 선언합니다.


List<Point2f> src_pts = new List<Point2f>()
{
    new Point2f(0.0f, 0.0f),
    new Point2f(0.0f, src.Height),
    new Point2f(src.Width, src.Height)
};

List<Point2f> dst_pts = new List<Point2f>()
{
    new Point2f(300.0f, 300.0f),
    new Point2f(300.0f, src.Height),
    new Point2f(src.Width - 400.0f, src.Height - 200.0f)
};

Mat matrix = Cv2.GetAffineTransform(src_pts, dst_pts);

아핀 변환을 진행하기 위해선, 아핀 맵 행렬을 생성해야 합니다.

아핀 맵 행렬 생성 함수(Cv2.GetAffineTransform)변환 전 세 개의 픽셀 좌표(src_pts)변환 후 세 개의 픽셀 좌표(dst_pts)를 이용해 아핀 맵 행렬(matrix)을 생성합니다.

Cv2.GetAffineTransform(변환 전 픽셀 좌표, 변환 후 픽셀 좌표)아핀 맵 행렬을 생성합니다.

픽셀 좌표3개의 픽셀 좌표를 포함해야 하므로, 목록(List)을 통해, Point2f 형식의 좌표를 생성합니다.

src_ptsdst_pts의 픽셀 좌표들의 순서는 1:1로 매칭됩니다.


Cv2.WarpAffine(src, dst, matrix, new Size(src.Width, src.Height));

생성된 아핀 행렬을 활용해 아핀 변환을 진행합니다.

아핀 변환 함수(Cv2.WarpAffine)는 아핀 행렬을 사용해 변환된 이미지를 생성합니다.

Cv2.WarpAffine(원본 배열, 결과 배열, 행렬, 결과 배열의 크기, 보간법, 테두리 외삽법, 테두리 색상)로 아핀 변환을 진행합니다.

결과 배열의 크기를 설정하는 이유는 회전 후, 원본 배열의 이미지 크기와 다를 수 있기 때문입니다.

이미지를 더 큰 공간에 포함하거나, 더 작은 공간에 포함할 수 있습니다.

그러므로, 결과 배열의 크기를 새로 할당하거나, 원본 배열의 크기와 동일하게 사용합니다.

보간법, 테두리 외삽법, 테두리 색상 또한, 새로운 공간에 이미지를 할당하므로, 보간에 필요한 매개변수들을 활용할 수 있습니다.



출력 결과

댓글 남기기