본문 바로가기

# 미사용/OpenCV

[OpenCV] 이진화 (1) 응용 : 로고넣기


 샘플 이미지

 간단 요약

로고 넣는 방법

  • 로고 형태의 흑백사진을 얻는다.

  • 로고 형태로 이미지에 흰색 구멍을 뚫는다.

  • 흰색 구멍에 로고를 채워넣는다.





 로고 형태의 흑백사진 얻기

필요한 변수들

//! 필요한 변수들
Mat logo_white_bg_ch3;              //! 로고 3채널 이미지 (BGR)
Mat logo_white_bg_ch3_rgb[3];       //! 로고 3채널 이미지의 각 채널.
Mat logo_mask_black_bg_c1;          //! 로고 검은색 배경 마스크 (BGR)
Mat logo_mask_white_bg_c1;          //! 로고 흰색 배경 마스크 (BGR)
Mat logo_mask_black_bg_c3;          //! 로고 검은색 배경 마스크 (Grayscale)
Mat logo_mask_white_bg_c3;          //! 로고 흰색 배경 마스크 (Grayscale)





STEP 1)

로고 이미지를 3채널로 불러오고, (Blue영상, Green영상, Red영상)으로 분리한다.

샘플에서 주어진 로고 이미지의 배경색은 흰색임에 주의한다.

//! 로고 이미지를 불러오고, 채널별로 분리한다.
logo_white_bg_ch3  = imread("./images/logo.png", IMREAD_COLOR);
split(logo_white_bg_ch3, logo_white_bg_ch3_rgb);







STEP 2)

위의 이미지에서 검정색인 부분을 모두 가져온다.

어떤색 and  검정색(0x000000) = 검정색 임을 이용하자.

//! 로고의 1채널 마스크를 얻는다.
logo_mask_white_bg_c1 = 
        logo_white_bg_ch3_rgb[0] & 
        logo_white_bg_ch3_rgb[1] & 
        logo_white_bg_ch3_rgb[2];
bitwise_not(logo_mask_white_bg_c1, logo_mask_black_bg_c1);







STEP 3)

3채널 이미지와 연산할 수 있도록,

마스크 이미지를 3채널로 변환한다.

//! 로고의 3채널 마스크로 변환.
cvtColor(logo_mask_black_bg_c1, logo_mask_black_bg_c3, COLOR_GRAY2BGR);
cvtColor(logo_mask_white_bg_c1, logo_mask_white_bg_c3, COLOR_GRAY2BGR);






 이미지에 로고 형태로 구멍 뚫기

필요한 변수들

//! 필요한 변수들
Mat image;                          //! 이미지
Mat roi;                            //! 이미지에서 로고가 위치할 영역의 참조영역
Mat roi_clone_masked_black_logo;    //! 참조영역 복사본에 검은색 로고 형태를 씌운 이미지.
Mat roi_clone_masked_white_logo;    //! 참조영역 복사본에 흰색 로고 형태를 씌운 이미지.
Mat roi_clone_with_logo;            //! 참조영역 복사본에 로고를 씌운 이미지.





STEP 1)

로고가 위치할 영역을 관심영역으로 설정한다.

//! 로고가 위치할 영역의 시작점을 구한다.
Point center1 = image.size()/2;
Point center2 = logo_white_bg_ch3.size() / 2;
Point logo_start = center1 - center2;


//! 로고가 위치할 영역을 관심영역으로 설정한다.
Rect rect_roi = Rect(logo_start, logo_white_bg_ch3.size());
roi = image(rect_roi);







STEP 2)

관심영역의 복사본을 생성하면서,

로고 형태로 검정색 구멍을 뚫는다. (마스크 기법 적용)

//! 이미지에 로고 형태로 검은색 구멍을 뚫는다.
copyTo(
    roi, 
    roi_clone_masked_black_logo, 
    logo_mask_white_bg_c1
);







STEP 3)

검정색 구멍을 흰색으로 변환한다.

어떤색 + 검정색(0x000000) = 어떤색 임을 이용한다. 

//! 검은색 구멍을 하얀색으로 덧칠한다.
roi_clone_masked_white_logo = 
    roi_clone_masked_black_logo + 
    logo_mask_black_bg_c3;







 흰색 구멍에 로고 채우기

STEP 1)

흰색 구멍에 로고를 채운다.

어떤색 and  흰색(0xFFFFFF) = 어떤색 임을 이용한다.

//! 하얀색 구멍에 로고를 씌운다.
roi_clone_with_logo = 
    roi_clone_masked_white_logo &
    logo_white_bg_ch3;







STEP 2)

완성된 로고영역을 원본 이미지에 씌운다.

//! 완성된 부분 이미지를 원본에 씌운다.
roi_clone_with_logo.copyTo(roi);







 전체 코드

#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;

int main() {
    //! 필요한 변수들
    Mat logo_white_bg_ch3;              //! 로고 3채널 이미지 (BGR)
    Mat logo_white_bg_ch3_rgb[3];       //! 로고 3채널 이미지의 각 채널.
    Mat logo_mask_black_bg_c1;          //! 로고 검은색 배경 마스크 (BGR)
    Mat logo_mask_white_bg_c1;          //! 로고 흰색 배경 마스크 (BGR)
    Mat logo_mask_black_bg_c3;          //! 로고 검은색 배경 마스크 (Grayscale)
    Mat logo_mask_white_bg_c3;          //! 로고 흰색 배경 마스크 (Grayscale)
    Mat image;                          //! 이미지
    Mat roi;                            //! 이미지에서 로고가 위치할 영역의 참조영역
    Mat roi_clone_masked_black_logo;    //! 참조영역 복사본에 검은색 로고 형태를 씌운 이미지.
    Mat roi_clone_masked_white_logo;    //! 참조영역 복사본에 흰색 로고 형태를 씌운 이미지.
    Mat roi_clone_with_logo;            //! 참조영역 복사본에 로고를 씌운 이미지.


    //! 이미지와 로고를 불러온다.
    image     = imread("./images/image.jpg", IMREAD_UNCHANGED);
    logo_white_bg_ch3  = imread("./images/logo.png", IMREAD_COLOR);
    imshow("logo_white_bg_ch3", logo_white_bg_ch3);


    //! 로고 이미지의 1채널 마스크를 얻는다.
    split(logo_white_bg_ch3, logo_white_bg_ch3_rgb);
    logo_mask_white_bg_c1 =
            logo_white_bg_ch3_rgb[0] &
            logo_white_bg_ch3_rgb[1] &
            logo_white_bg_ch3_rgb[2];
    bitwise_not(logo_mask_white_bg_c1, logo_mask_black_bg_c1);
    imshow("logo_mask_white_bg_c1", logo_mask_white_bg_c1);
    imshow("logo_mask_black_bg_c1", logo_mask_black_bg_c1);


    //! 로고 이미지의 3채널 마스크를 얻는다.
    cvtColor(logo_mask_black_bg_c1, logo_mask_black_bg_c3, COLOR_GRAY2BGR);
    cvtColor(logo_mask_white_bg_c1, logo_mask_white_bg_c3, COLOR_GRAY2BGR);
    imshow("logo_mask_black_bg_c3", logo_mask_black_bg_c3);
    imshow("logo_mask_white_bg_c3", logo_mask_white_bg_c3);


    //! 이미지에서 로고가 위치할 영역의 시작지점을 구한다.
    Point center1 = image.size()/2;
    Point center2 = logo_white_bg_ch3.size() / 2;
    Point logo_start = center1 - center2;


    //! 로고가 위치할 영역을 관심영역으로 설정한다.
    Rect rect_roi = Rect(logo_start, logo_white_bg_ch3.size());
    roi = image(rect_roi);
    imshow("roi", roi);


    //! 이미지에 로고 형태로 검은색 구멍을 뚫는다.
    copyTo(roi, roi_clone_masked_black_logo, logo_mask_white_bg_c1);
    imshow("roi_clone_masked_black_logo", roi_clone_masked_black_logo);


    //! 검은색 구멍을 하얀색으로 덧칠한다.
    roi_clone_masked_white_logo = roi_clone_masked_black_logo + logo_mask_black_bg_c3;
    imshow("roi_clone_masked_white_logo", roi_clone_masked_white_logo);


    //! 하얀색 구멍에 로고를 씌운다.
    roi_clone_with_logo = roi_clone_masked_white_logo & logo_white_bg_ch3;
    imshow("roi_clone_with_logo", roi_clone_with_logo);


    //! 완성된 부분 이미지를 원본에 씌운다.
    roi_clone_with_logo.copyTo(roi);
    imshow("image", image);
    waitKey();
}