▶ 두 개의 영상 가중합 하기
영상끼리 더해주거나 빼주거나 곱해주거나 나누어주는 것이 가능하다. 오늘은 두 영상을 가중합하는 것을 해보도록 하겠다. 화창한 이미지에 비 이미지를 더해서 마치 비가 오는 것처럼 만들 것이다.
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", 에이콘
'Dev > C, C++' 카테고리의 다른 글
[opencv와 C++로 컴퓨터 비전] 영상 재매핑 처리 (0) | 2018.03.21 |
---|---|
[opencv와 C++로 컴퓨터 비전] 영상 선명하게 만들기 (0) | 2018.03.07 |
[opencv와 C++로 컴퓨터 비전] 영상 내 컬러 개수 감소 (0) | 2018.02.15 |
제가 심심풀이로 만든 저격수 훈련 게임: '아임스나이퍼' (은근 중독성 있음) (18) | 2018.02.06 |
[opencv와 C++로 컴퓨터 비전] 예쁜 타이머 만들기 (타이머 종료시 음악 재생) (6) | 2018.02.02 |
[opencv와 C++로 컴퓨터 비전] 영상에 소금-후추 잡음(salt-and-pepper noise) 넣기 (2) | 2018.02.01 |
[opencv와 C++로 컴퓨터 비전] 영상 위에 로고 넣기 (0) | 2018.01.31 |
[opencv와 C++로 컴퓨터 비전] 영상 위에 그림 그리기 및 글쓰기 (0) | 2018.01.30 |