2018-03-19 12:52:32

▶ 두 개의 영상 가중합 하기



영상끼리 더해주거나 빼주거나 곱해주거나 나누어주는 것이 가능하다. 오늘은 두 영상을 가중합하는 것을 해보도록 하겠다. 화창한 이미지에 비 이미지를 더해서 마치 비가 오는 것처럼 만들 것이다. 


1. 두 개의 영상 읽기

2. 영상 가중합- cv::addWeighted 함수

3. 또 다른 방식으로 영상 가중합

4. BGR중에 G, 초록 채널에만 영상 가중합(초록비 내리게 함)- cv::split 함수, cv::merge 함수


코드는 아래와 같다.


#include <iostream>

#include <opencv2\highgui.hpp>

#include <opencv2\core.hpp>

#include <opencv2/imgproc.hpp> // cv::cvtColor 함수를 사용하기 위해 필요. 


int main()

{

/* 2개의 컬러 이미지 가중합 */

cv::Mat img1 = cv::imread("marco.jpg");

cv::imshow("img1", img1);

cv::Mat img2 = cv::imread("rain.jpg");

cv::imshow("img2", img2);

cv::Mat result;

cv::addWeighted(img1, 0.7, img2, 0.9, 0.0, result); // result = 0.7 * img1 + 0.9 * img2 + 0.0

cv::imshow("Result", result);


/* 다른 방식으로 2개의 컬러 이미지 가중합 */

cv::Mat result1;

result1 = 0.7*img1 + 0.9*img2;

cv::imshow("Result1", result1);



/* 초록 채널에만 2개의 이미지 가중합 */

cv::Mat img2_gray;

cv::Mat result2;

cv::cvtColor(img2, img2_gray, CV_BGR2GRAY); // 컬러 영상이던 img2를 그레이 영상으로 변환. 


std::vector<cv::Mat> planes; // 3개 영상의 벡터 생성

cv::split(img1, planes); // 3채널인 단일 영상을 3개의 1채널 영상으로 분리

planes[1] += img2_gray; // 초록 채널에 더하기

cv::merge(planes, result2); // 3개의 1채널 영상을 3채널인 단일 영상으로 병합

cv::imshow("Result2", result2);



cv::waitKey(0);

    return 0;

}


구현된 결과 전시된 이미지들은 아래와 같다. 




화창했던 크로아티아 자그레브의 마르코 성당이 비가 내리는 모습으로 바뀌었다. 그리고 마지막 이미지를 보면 비의 색이 초록색임을 알 수 있다. 



▶ 좀 더 알고 넘어갈 것들


1) 영상 가중합


가중합을 두 가지의 방식으로 구현했다. 하나는 cv::addWeighted 함수를 사용한 것이고, 하나는 좀 더 직관적으로 result = 0.7*img1 + 0.9*img2와 같은 방식으로 가중합했다.


 cv::addWeighted(img1, 0.7, img2, 0.9, 0.0, result); // result = 0.7 * img1 + 0.9 * img2 + 0.0


result1 = 0.7*img1 + 0.9*img2;



2) 컬러 이미지를 그레이 이미지로 전환하기


컬러 이미지를 그레이 이미지로 전환하기 위해 cv::cvtColor 함수를 활용했다. 이 함수를 사용하기 위해서는 해더에 아래와 같이 선언해줘야 한다.


#include <opencv2/imgproc.hpp>


컬러 영상을 그레이로 변환하기 위해 간단히 아래와 같이 코딩하면 된다. 


cv::cvtColor(img2, img2_gray, CV_BGR2GRAY); 


cv::cvtColor 함수는 RGB 영상을 그레이영상으로 변환해주는 것 뿐만 아니라, HSV, LUV, LAB 등의 색 공간으로도 변환해 줄 수 있다. 


3) cv::split 함수와 cv::merge 함수


cv::split 함수는 3채널인 영상을 3개의 1채널 영상으로 분리해준다. 위 예제에서는 마르코 성당 이미지를 3개의 1채널 영상으로 분리해줬다(B채널, G채널, R채널). 분리한 이유는 G채널에만 비 영상을 더해 주기 위함이다. 3채널 비 영상을 1채널 그레이 영상을 전환한 다음에 성당 이미지의 G채널에만 더해준다. 결과적으로 비가 지나간 자리는 초록색이 된다. 그리고 cv::merge 함수를 이용해서 분리된 3개의 채널을 다시 하나의 3채널 컬러 영상을 생성한다. 


/* 초록 채널에만 2개의 이미지 가중합 */

cv::Mat img2_gray;

cv::Mat result2;

cv::cvtColor(img2, img2_gray, CV_BGR2GRAY); // 컬러 영상이던 img2를 그레이 영상으로 변환. 


std::vector<cv::Mat> planes; // 3개 영상의 벡터 생성

cv::split(img1, planes); // 3채널인 단일 영상을 3개의 1채널 영상으로 분리

planes[1] += img2_gray; // 초록 채널에 더하기

cv::merge(planes, result2); // 3개의 1채널 영상을 3채널인 단일 영상으로 병합



<참고자료>

[1] 로버트 라가니에 지음, 이문호 옮김, "OpenCV를 활용한 컴퓨터 비전 프로그래밍 3/e", 에이콘