[OpenCV] 영상 산술 연산 – 1. 덧셈, 뺄셈

안녕하세요 이번 글에서는 영상에서의 산술 연산에 대해 알아보겠습니다.

OpenCV에서 영상은 행렬로 표현하기 때문에 두개의 영상을 더하거나 빼는 연산을 수행할 수 있습니다.
영상의 덧셈, 뺄셈, 곱셈, 나눗셈 모두 가능하지만 곱하기, 나누기는 잘 사용하지 않습니다.
먼저 덧셈, 뺄셈 연산에 대해 알아보겠습니다.

덧셈

OpenCV에서는 덧셈 연산을 할 경우 add() 함수를 사용합니다.

/** 
@param src1 입력 영상1
@param src2 입력 영상2
@param dst 입력 영상 1, 2에 대한 add 출력 결과
@param mask 8비트 1채널 마스크 영상
@param dtype 출력 행렬의 깊이
*/
void add(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);

샘플 코드는 아래와 같습니다.

Mat src1 = imread("lenna.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("square.bmp", IMREAD_GRAYSCALE);

if (src1.empty() || src2.empty())
{
	cerr << "image load fail" << endl;
	return;
}

Mat dst1;
add(src1, src2, dst1); // 영상 덧셈

imshow("src1", src1);
imshow("src2", src2);
imshow("dst1", dst1);

waitKey();

destroyAllWindows();

실행 결과는 아래와 같습니다.

addWeighted 함수를 사용하면 두 영상을 더할 때 가중치를 부여하여 덧셈을 할 수 있습니다. addWeighted 함수는 아래와 같습니다.

/** 
@param src1 입력 영상 1
@param alpha 입력 영상 1의 가중치
@param src2 입력 영상 2
@param beta 입력 영상 2의 가중치
@param gamma 결과에 추가로 더할 값
@param dst 출력 영상
@param dtype 출력 행력 깊이
*/
void addWeighted(InputArray src1, double alpha, InputArray src2, double beta, double gamma, OutputArray dst, int dtype = -1);

위 코드에 아래 addWeighted 함수를 추가한 샘플입니다.

Mat dst3;
addWeighted(src1, 0.3, src2, 0.5, 0.2, dst3); // 가중치가 부여된 영상 덧셈

imshow("dst3", dst3);
waitKey();

destroyAllWindows();

실행 결과는 아래와 같습니다.

가중치가 부여되어서 영상이 전반적으로 어두워진 것을 볼 수 있습니다.

뺄셈

이번엔 뺄셈에 대해 알아보겠습니다. 뺄셈은 subtract 함수를 사용합니다.

/**
@param src1 입력 영상 1
@param src2 입력 영상 2
@param dst 출력 영상
@param mask 8비트 1채널 마스크 영상
@param dtype 출력 행렬의 깊이
*/
void subtract(InputArray src1, InputArray src2, OutputArray dst, InputArray mask = noArray(), int dtype = -1);

샘플 코드는 아래와 같습니다.

Mat src1 = imread("lenna.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("square.bmp", IMREAD_GRAYSCALE);

if (src1.empty() || src2.empty())
{
	cerr << "image load fail" << endl;
	return;
}

Mat dst1, dst2;
// 영상 뺄셈
subtract(src1, src2, dst1);
subtract(src2, src1, dst2);

imshow("src1", src1);
imshow("src2", src2);
imshow("dst1", dst1);
imshow("dst2", dst2);

waitKey();

destroyAllWindows();

실행 결과는 아래와 같습니다.

위에서 나온 결과처럼 subtract함수를 사용하여 영상의 뺄셈을 할 경우 조심해야 할 것은 뺄셈의 순서를 잘 지켜야 한다는 것입니다. 6+2와 2+6은 8이지만 6-2와 2-6이 결과가 다른 것과 같은 상황입니다.

이런 경우 차이 연산을 하면 됩니다. 차이 연산은 뺄셈 연산 결과에 절대값을 취하는 연산입니다.
차이 연산은 absdiff 함수를 사용하면 됩니다.

/** 
@param src1 입력 영상1
@param src2 입력 영상2
@param dst 출력 영상
*/
void absdiff(InputArray src1, InputArray src2, OutputArray dst);

샘플 코드는 아래와 같습니다.

Mat src1 = imread("lenna.bmp", IMREAD_GRAYSCALE);
Mat src2 = imread("square.bmp", IMREAD_GRAYSCALE);

if (src1.empty() || src2.empty())
{
	cerr << "image load fail" << endl;
	return;
}

Mat dst1;
absdiff(src1, src2, dst1); // 차이 연산

imshow("src1", src1);
imshow("src2", src2);
imshow("dst1", dst1);

waitKey();
destroyAllWindows();

실행 결과는 아래와 같습니다.

이상으로 영상의 덧셈, 뺄셈에 대해 알아봤습니다.