C# OpenCV Transformation

2021. 1. 17. 09:00OpenCV/OpenCV C#

반응형

1. 이미지 확대 & 축소

확대 함수(Cv2.PyrUp) 또는 축소 함수(Cv2.PyrDown)를 활용해 이미지를 변환한다.

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            Mat dst = new Mat(src.Size(), MatType.CV_8UC3);
            Mat dst2 = new Mat(src.Size(), MatType.CV_8UC3);

            // Cv2.PyrUp(src, dst, new Size(src.Width * 2 + 1, src.Height * 2 - 1));
            Cv2.PyrUp(src, dst);
            Cv2.PyrDown(src, dst2); //4배 축소
            Cv2.PyrDown(dst2, dst2); //16배 축소

            Cv2.ImShow("src", src);
            Cv2.ImShow("dst", dst);
            Cv2.ImShow("dst2", dst2);

            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
    }
}

 

실행결과

1



2. 이미지 크기 조절

크기 조절 함수(Cv2.Resize)를 활용해 이미지를 변환한다.

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            Mat dst = new Mat();
            Mat dst2 = new Mat();

            Cv2.Resize(src, dst, new Size(500, 250)); // 절대적 크기
            Cv2.Resize(src, dst2, new Size(0, 0), 0.5, 0.5); // 상대적 크기

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

 

실행결과

2



3. 이미지 대칭

대칭 함수(Cv2.Flip)를 활용해 이미지를 변환한다.

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            Mat dst = new Mat(src.Size(), MatType.CV_8UC3);
            Mat dst2 = new Mat(src.Size(), MatType.CV_8UC3);
            Mat dst3 = new Mat(src.Size(), MatType.CV_8UC3);

            Cv2.Flip(src, dst, FlipMode.Y); // Y축대칭
            Cv2.Flip(src, dst2, FlipMode.X); // X축대칭
            Cv2.Flip(src, dst3, FlipMode.XY); // XY축대칭

            Cv2.ImShow("src", src);
            Cv2.ImShow("dst", dst);
            Cv2.ImShow("dst2", dst2);
            Cv2.ImShow("dst3", dst3);
            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
    }
}

 

실행결과

3



4. 이미지 회전

이미지를 회전시키기 위해, 회전 행렬을 생성한다.

2×3 회전 행렬 생성 함수(Cv2.GetRotationMatrix2D)는 Mat 형식의 회전 행렬을 생성한다.

Cv2.GetRotationMatrix2D(중심점의 좌표, 회전 각도, 비율)로 회전 행렬을 생성한다.

중심점의 좌표를 기준으로 회전 각도만큼 회전하며, 비율만큼 크기를 변경한다.

 

생성된 회전 행렬을 활용해 아핀 변환을 진행한다.

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

Cv2.WarpAffine(원본 배열, 결과 배열, 행렬, 결과 배열의 크기)로 회전 행렬을 생성한다.

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

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            Mat dst = new Mat();
            Mat dst2 = new Mat();
            Mat dst3 = new Mat();

            Mat matrix = Cv2.GetRotationMatrix2D(new Point2f(src.Width / 2, src.Height / 2), 90.0, 1.0);
            Mat matrix2 = Cv2.GetRotationMatrix2D(new Point2f(src.Width / 2, src.Height / 2), 180.0, 1.0);
            Mat matrix3 = Cv2.GetRotationMatrix2D(new Point2f(src.Width / 2, src.Height / 2), 45.0, 1.0);

            Cv2.WarpAffine(src, dst, matrix, new Size(src.Width, src.Height)); // 아핀변환 함수를 적용
            Cv2.WarpAffine(src, dst2, matrix2, new Size(src.Width, src.Height));
            Cv2.WarpAffine(src, dst3, matrix3, new Size(src.Width, src.Height));

            Cv2.ImShow("src", src);
            Cv2.ImShow("dst", dst);
            Cv2.ImShow("dst2", dst2);
            Cv2.ImShow("dst3", dst3);

            Cv2.WaitKey(0);
            Cv2.DestroyAllWindows();
        }
    }
}

 

실행결과

4



5. 아핀 변환

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

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

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

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

src_pts와 dst_pts의 픽셀 좌표들의 순서는 1:1로 매칭된다.

 

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

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

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

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

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            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(50.0f, 50.0f),
               new Point2f(0.0f, src.Height - 100.0f),
               new Point2f(src.Width - 50.0f, src.Height - 50.0f)
            };

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

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

 

실행결과

6



5. 원근 변환

아핀 변환과 비슷하지만 선의 수평성을 유지하지 않고, 직선의 성질만 유지되며 사각형을 임의의 사각형 형태로 변환하는 것을 의미한다.

원근 변환은 뒤틀림이나 원근 왜곡을 표현해야 하므로 아핀 변환에 비해 더 많은 미지수를 요구한다.

실행코드

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OpenCvSharp;

namespace Transformation
{
    class Program
    {
        static void Main(string[] args)
        {
            Mat src = Cv2.ImRead("../../opencv.png");
            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),
                new Point2f(src.Width, 0.0f)
            };

            List<Point2f> dst_pts = new List<Point2f>()
            {
               new Point2f(50.0f, 50.0f),
               new Point2f(0.0f, src.Height),
               new Point2f(src.Width, src.Height),
               new Point2f(src.Width - 100.0f, 0.0f)
            };

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

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

 

실행결과

7



출처

https://076923.github.io/posts/#Python-OpenCV

반응형

'OpenCV > OpenCV C#' 카테고리의 다른 글

C# OpenCV QRcode scanner  (0) 2021.01.27
C# OpenCV labeling  (0) 2021.01.19
C# OpenCV labeling Segmentation  (0) 2021.01.12
C# OpenCV histogram gray color BGR 그리기  (0) 2021.01.09
C# OpenCV 이미지 전처리  (0) 2021.01.06