Programming/Qt

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

변화의 물결1 2024. 3. 2. 00:03

 

 

안녕하세요.

 

  이번에는 이미지를 만화처럼 보이게 하는 효과를 플러그인 기능으로 만들어 보도록 하겠습니다. 프로젝트 만드는 방법은 이전 Sharpen 내용과 동일하기 때문에 필요하다면 이전 내용을 참조하시면 됩니다. 그럼 새로운 라이브러리 프로젝트를 생성한 후 진행하시면 됩니다.

 


 

1.  소스 코드 시작 전

 

  - 프로젝트명을 Cartoon_plugin으로 하고 클래스 이름은 CartoonPlugin으로 만드시면 됩니다. 그리고 CartoonPlugin::name() 함수와 CartoonPlugin::edit() 함수를 선언하고 정의하면 됩니다.

 

 - 우선 첫 번째 작업은 색상 팔레트를 축소시키는 것입니다. 그렇게 하기 위해서는 OpenCV 라이브러리에서 제공하는 bilateral filter를 사용합니다. 필터는 매끄럽게 하고 날카로운 가장자리를 유지하여 일반적인 RGB 이미지에 만화와 같은 느낌을 제공하지만 Gaussian Blur Algorithm 보다 느립니다. 응용프로그램에서 UI가 업데이트되지 않을 수 있습니다.

 그래서 시간을 단축할 수 있는 방법으로 원본 이미지의 크기 축소한 다음 축소된 버전에 필터를 적용하는 방법입니다.

 

 

2. 소스 코드 추가하기

 

 - 소스코드는 .cpp 파일에 void CartoonPlugin::edit(const cv::Mat &input, cv::Mat &output) 내 정의하면 됩니다.

 - 입력(Input) 원본을 받을 변수 copy1과 프로그램 처리된 영상을 임시로 저장해 둘 변수를 copy2를 만듭니다.

 

 - pyrDown() 함수를 통해 축소를 진행하지만 축소된 이미지를 다시 제 축소 기능이 되지 않아서 임시로 copy2 복사한 다음 다시 축소하는 형태로 되어 있습니다.

 - bilateralFilter 함수도 처리한 결과를 다시 입력으로 할 수가 없어서 copy2 변수를 사용하고 있습니다.

 

첫 번째 인자(src)는 입력 이미지이고, 두 번째 인자(dst)는 출력 이미지입니다.

세 번째 인자(d)는 필터링을 이용하는 이웃한 픽셀의 지름을 정의합니다. 불가능할 경우 sigmaspcae(다섯 번째 인자)를 이용합니다.

 네 번째 인자(sigmaColor)는 공간 컬러의 시그마 공간 정의이고, 클수록 이웃한 픽셀과 기준 색상에 영향이 커집니다.

 다섯 번째 인자(sigmaSpace)는 시그마 필터를 조정합니다. 값이 클수록 주변 픽셀에 영향을 주게 되고 d>0 이면 영향을 받지 않고 그 외에는 d 값에 비례합니다. 

 

 - 원래 이미지로 크기를 확대하기 위해 pyrUp() 함수를 호출합니다.

 

 

         int num_down = 2;
         int num_bilateral = 7;

		 cv::Mat copy1, copy2;

		 copy1 = input.clone();
         for(int i = 0; i < num_down; i++) {
             cv::pyrDown(copy1, copy2);
             copy1 = copy2.clone();
         }

         for(int i = 0; i < num_bilateral; i++) {
             cv::bilateralFilter(copy1, copy2, 9, 9, 7);
             copy1 = copy2.clone();
         }

         for(int i = 0; i < num_down; i++) {
             cv::pyrUp(copy1, copy2);
             copy1 = copy2.clone();
         }

 

 

- 이미지 확대 축소로 인해 이미지 행렬의 크기가 다를 수 있기 때문에 크기 원본 이미지 크기와 맞도록 조정해 줍니다.

 

 

if (input.cols != copy1.cols || input.rows != copy1.rows) {
	cv::Rect rect(0, 0, input.cols, input.rows);
	copy1(rect).copyTo(copy2);
	copy1 = copy2;
}

 

 

 - 그림의 에지(가장자리)를 감지할 수 실루엣을 만듭니다. 가장자리를 감지를 위해서 OpenCV에서 제공해 주는 cv::adaptiveThreshold 함수와 임계값(Threshold) 유형으로 cv::THRESH_BINARY를 사용하여 호출합니다. 이는 현재 픽셀 주변의 작은 영역에 있는 픽셀에 의해 결정되는 동적 임계값을 사용하는 것입니다. 그러나 단점은 노이즈 영향을 받기 쉽기 때문입니다.

 

  그래서 cv2.medianBlur을 사용하여 흐릿한 그레이 스케일 이미지의 노이즈를 줄입니다. 흐림 값이 클수록 이미지에 나타나는 검은색 노이즈가 줄어듭니다. 그런 다음 adaptiveThreshold 기능을 적용하고 가장자리의 선 크기를 정의합니다. 선 크기가 클수록 이미지에서 강조되는 가장자리가 두꺼워집니다. 여기서 9는 Line Size이고 2는 Blur 값이 됩니다.

 

 

cv::Mat image_gray, image_edge;

cv::cvtColor(input, image_gray, cv::COLOR_RGB2GRAY);
cv::medianBlur(image_gray, image_gray, 5);

cv::adaptiveThreshold(image_gray, image_gray, 255,
	cv::ADAPTIVE_THRESH_MEAN_C, cv::THRESH_BINARY, 9, 2);
cv::cvtColor(image_gray, image_edge, cv::COLOR_GRAY2RGB);

  

 

 - 이제 색상이 축소 처리된 이미지와 에지 마스크를 비트단위 연산(and 연산자)을 사용해서 결합시킵니다.

 

 

output = copy1 & image_edge;

 

 

3. 최종 결과

 

 - 문제없이 컴파일이 될 경우 cartoon_plugin.dll 파일이 만들어집니다. 그 후에 image_editor debug 폴더에 복사해서 넣고 image_editor를 실행시키면 Cartoon 메뉴가 생성되어 있습니다.

 - 이미지 하나를 불러옵니다.

 

 

 

 

 - Cartoon 효과가 적용된 것을 알 수 있습니다. 인자 값 등을 조절해서 조금 더 이미지에 변화를 주어도 됩니다.

 

 

 

감사합니다.

   

 

<참고 사이트>

1. [BOOK] Qt-5-and-OpenCV-4-Computer-Vision-Projects

2. Python을 사용하여 사진을 만화로 바꾸는 방법

http://insightcampus.co.kr:9090/insightcommunity/?uid=12967&mod=document&pageid=1

3. [OpenCV] Bilateral Filter 적용하기

https://eehoeskrap.tistory.com/125    

 

cartoon_plugin.zip
0.00MB

반응형