Programming/Qt

[도서 실습] Qt 5 and OpenCV 4 Computer Vision – ImageEditor (Plugin Mechanism – Rotating Images)

변화의 물결1 2024. 3. 8. 00:01

 

 

안녕하세요.

 

  이번에는 이미지를 회전시키는 플러그인을 추가해 보도록 하겠습니다. 간편하게 rotate() 함수를 호출해서는 되지 않고 몇 가지 개념을 가지고 회전을 시켜야 했습니다. 


 

1.  소스 코드 시작 전

 

1) 기하학적 변형(Geometric transformations)

 

  - 책 내용처럼 쉽게 생각해서 이미지만 회전시키면 되겠지 생각할 수 있지만, 조금 자료를 찾아보면 기하학이라는 좌표 개념과 수학적 지식이 필요했습니다. 간단하게 정의를 살펴보면,

 

  "영상의 기하학적 변형이란 화소의 위치를 변화하여 원 영상과는 다른 내용을 갖는 것을 말한다. 이러한 기하학적 변형에는 좌우 교환, 상하 교환, 평행 이동, 확대 및 축소, 회전 변형 등이 있다. 기하학적인 변형을 수학적으로 표현하기 위하여 변형되기 전의 화소의 위치를 (x, y)로 표기하고, 이에 대응하는 변형된 좌표를 (X, Y)로 표현한다."

 

 와 같고, 변형에 따른 행렬공식은 아래의 링크를 참고하면 도움이 될 것이라 생각됩니다.

 

 예) 좌우 교환 : 한 수직선을 중심으로 좌측 화소와 우측 화소를 서로 교환하는 방식

 

 

 

http://image.chungbuk.ac.kr/jhahn/lecture/mip/image/notes/3-geo.html

 

2) 플러그인(Plugin) 프로젝트 생성

 

 - 플러그인 만드는 방식은 이전 내용과 동일합니다.

 - 흐름만 다시 보면, Library프로젝트 선택 -> 이름을 RotatePlugin 지정 및 qmake 컴파일러 설정 -> pro 파일 OpenCV 경로 추가-> RotatePlugin_global.h 삭제하고 editor_plugin_interface.h 파일 복사 -> name 함수와 edit 함수 추가 -> rotate_plugin.dll 파일 ImageEditor/plugin 폴더로 복사

 

 

2. 소스코드 추가하기

 

 - edit 함수를 간단하게 Plugin 이름을 "Rotate"로 지정해 줍니다.

 

QString RotatePlugin::name()
{
    return "Rotate";
}

 

 

 - 회전을 위한 코드 edit() 함수를 작성합니다. 그전에 2가지 함수에 대해 알아보겠습니다.

 

 1) warpAffine() 함수 :  이미지의 위치를 변경하는 함수라고 생각하시면 됩니다.

 

  첫 번째 인자(src)는 원본 이미지,

 

  두 번째 인자는(dst)는 변환된 결과 이미지,

  세 번째 인자는(M) 변환 행렬로 위치를 어떻게 변경해야 하는 행렬 자료 (2 × 3 transformation matrix)를 참고하게 됩니다.

 

  네 번째 인자(dsize)는 출력 이미지의 크기,

 

  다섯 번째 인자(flags)는 보간법(interpolation)으로 간단히 설명을 참고하자면,

 "이미지의 크기를 변경하는 경우, 변형된 이미지의 픽셀은 추정해서 값을 할당해야 합니다. 이미지의 비율을 변경하면 존재하지 않는 영역에 새로운 픽셀 값을 매핑하거나 존재하는 픽셀들을 압축해서 새로운 값을 할당해야 합니다."

 

 그래서 추정해야 하는 픽셀은 보간법을 이용하여 픽셀들의 값을 할당해야 합니다. 이를 이미지 상에 존재하는 픽셀 데이터 (xi, yi)들에 대해 근사 함수 f(x, y)를 적용해서 새로운 픽셀 값을 구하는 것으로 이해할 수 있습니다. 일반적인 경우, 쌍 선형 보관법(INTER_LINEAR)을 사용한다고 합니다.

 

  여섯 번째 인자(BorderMode)는 보더 타입(Border Type)으로 BORDER_CONSTANT라고 하면 회전 후 일부 영역이 원본 이미지로 덮이지 않으면 일정한 색상으로 채워집니다. 이 색상을 일곱 번째 인수로 지정할 수 있습니다. 입력하지 않으면 기본으로 검은색이 사용됩니다.

  

 

2) getRotationMatrix2D 함수

 

  물체를 평면상의 한 점을 중심으로 𝜃 만큼 회전하는 함수입니다. 양의 각도는 시계 반대방향으로 회전을 합니다. 그리고 출력 결과는 변환 행렬을 반환합니다.

  center – 이미지의 중심 좌표

  angle – 회전 각도

  scale – scale factor

 

 

void RotatePlugin::edit(const cv::Mat &input, cv::Mat &output)
{
    double angle = 45.0;
    double scale = 1.0;
    
    cv::Point2f center = cv::Point(input.cols/2, input.rows/2);
    cv::Mat rotateMatrix = cv::getRotationMatrix2D(center, angle, scale);

    cv::Mat result;
    cv::warpAffine(input, result,
       rotateMatrix, input.size(),
       cv::INTER_LINEAR, cv::BORDER_CONSTANT);
    output = result;
}

 

 

3. 최종 결과

 

 - RotatePlugin.dll 파일을 debug/plugin 폴더에 복사하고 ImageEditor 실행시킵니다.

 

 

 

- Rotate 메뉴가 생성된 것을 확인할 수 있고, 한번 클릭할 경우 45도로 회전된 것을 확인할 수 있습니다.

 

 

 

 

감사합니다.

 

 

<참고 사이트>

1. 제3 장 영상의 기하학적 변형

http://image.chungbuk.ac.kr/jhahn/lecture/mip/image/notes/3-geo.html

2. 이미지의 기하학적 변형

https://opencv-python.readthedocs.io/en/latest/doc/10.imageTransformation/imageTransformation.html

3. [영상 Geometry #1] 좌표계

https://darkpgmr.tistory.com/77?category=460965

4. Python OpenCV 강좌 : 제8강 - 크기 조절

https://076923.github.io/posts/Python-opencv-8/

5. OpenCV | 어파인 변환

https://velog.io/@nayeon_p00/OpenCV-%EC%96%B4%ED%8C%8C%EC%9D%B8-%EB%B3%80%ED%99%98

6. warpAffine()

https://docs.opencv.org/4.5.2/da/d54/group__imgproc__transform.html#ga0203d9ee5fcd28d40dbc4a1ea4451983  

 

RotatePlugin.zip
0.00MB

반응형