[OpenCV] 그레이스케일에서 영상 밝기

이번 글에서는 영상의 밝기에 대해 알아보겠습니다.

그레이스케일 영상에서 픽셀값은 0 ~ 255 값을 가지는데 255에 가까울수록 밝아지고,  0에 가까울수록 어두워집니다.

영상 밝기를 증가시키는 코드는 아래와 같습니다.

Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
	cerr << "image load fail" << endl;
	return -1;
}

Mat dst = src + 150; // 모든 픽셀 150 증가

imshow("src", src);
imshow("dst", dst);

waitKey();
destroyAllWindows();

반대로 영상을 어둡게 할 경우 아래와 같이 마이너스 연산을 하면 됩니다.

Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
	cerr << "image load fail" << endl;
	return -1;
}

Mat dst = src - 100; // 모든 픽셀 100 감소

imshow("src", src);
imshow("dst", dst);

waitKey();
destroyAllWindows();

위와 같은 방법으로 할 경우 픽셀 값이 0보다 작거나, 255보다 크게 연산 결과가 나오더라도 자동으로 0과 255로 맞춰지게 됩니다. 이런 연산을 포화(saturate) 연산이라고 부릅니다.

하지만 직접 원소에 접근하여 값을 변경하는 경우, 위와 같이 자동으로 최대값, 최소값을 조절하지 않습니다.

아래 코드는 샘플 코드 입니다.

Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty())
{
	cerr << "image load fail" << endl;
	return -1;
}

Mat dst(src.rows, src.cols, CV_8UC1);

for (int iRow = 0 ; iRow < src.rows ; iRow++)
{
	for (int iCol = 0 ; iCol < src.cols ; iCol++)
	{
		dst.at<uchar>(iRow, iCol) = src.at<uchar>(iRow, iCol) + 100; // 원소마다 밝기를 100 증가
	}
}

imshow("src", src);
imshow("dst", dst);

waitKey();
destroyAllWindows();

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

원소에 직접 연산을 하니까 포화연산이 되지 않았습니다. 이런 경우를 대비하여 OpenCV에서는 포화연산을 수행하는 함수를 제공합니다.

template<> inline uchar
saturate_cast<uchar>(int v)
{
	return (uchar)((unsigned)v <= UCHAR_MAX ? v : v > 0 ? UCHAR_MAX : 0);
}

위 함수를 사용하여 코드를 실행할 경우 아래와 같이 포화연산을 수행합니다.

dst.at<uchar>(iRow, iCol) = saturate_cast<uchar>(src.at<uchar>(iRow, iCol) + 100);