[OpenCV] 2. 히스토그램 개념

이번 글에서는 히스토그램(Histogram)에 대해 알아보겠습니다.

그레이스케일 영상에서 히스토그램은 픽셀의 밝기값의 분포를 그래프 형태로 나타낸 을 말합니다.

위와 같은 4X4 크기의 이미지가 있습니다.
위 이미지는 0 ~ 7값을 가지며, 각 값들의 개수를 세어서 그래프 형태로 표현한 그림은 아래 그림과 같습니다.

위 그래프를 히스토그램 그래프라고 합니다.
여기서 X축을 히스토그램 빈(bin)이라고 하고, 그레이스케일 영상에서는 0 ~ 255의 값을 가지므로 히스토그램 빈 개수는 보통 256개입니다.

이 히스토그램을 구하는 함수는 다음과 같습니다.

/** 
@param images 입력 영상
@param nimages 입력 영상 개수
@param channels 히스토그램을 구하기 위해 사용되는 채널
@param mask 마스크 영상. 입력 영상과 같은 8비트 배열.
@param hist 출력 히스토그램
@param dims 히스토그램 차원
@param histSize A히스토그램 크기
@param ranges 히스토그램 빈 개수를 나타내는 배열
@param uniform 히스토그램이 균일한지 여부를 나타내는 플래그
@param accumulate 누적 플래그
*/
void calcHist( const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform = true, bool accumulate = false );

히스토그램을 구하는 간단한 예제는 아래와 같습니다.

// 히스토그램 구하기
Mat src = imread("lenna.bmp", CV_8UC1);
if (src.empty())
{
	cerr << "image open error" << endl;
	return -1;
}

int iImages = 1;
int iChannels[] = { 0 };
Mat histogram;
int iDims = 1;
const int iHistogramSize[] = { 256 };
float graylevel[] ={0, 256};
const float *pRanges[] = { graylevel };

calcHist(&src, iImages, iChannels, noArray(), histogram, iDims, iHistogramSize, pRanges);

위와 같은 코드를 실행 할 경우 Mat histogram은 256 X 1 크기를 가지며, 여기서 256은 히스토그램 빈 개수를 의미하며 히스토그램 값을 가지게 됩니다.
Mat histogram은 cout을 통해 값을 확인할 수 있지만 이것은 보기에 직관적이지 않습니다.

아래와 같이 코딩하면 히스토그램을 영상으로 표현할 수 있습니다.

// histogram 그리기
double dbMax; // 히스토그램에서 제일 큰 값
minMaxLoc(histogram, 0, &dbMax);

Mat histogram_img(100, 256, CV_8UC1, Scalar(255, 255, 255));
for (int iRow = 0 ; iRow < 256 ; iRow++)
{
	float val_hist = histogram.at<float>(iRow, 0);
	int iPos = cvRound(val_hist * 100 / dbMax);
	line(histogram_img, Point(iRow, 100), Point(iRow, 100 - iPos), Scalar(0,0,0));
}

imshow("src", src);
imshow("histogram", histogram_img);

waitKey();
destroyAllWindows();

실행하면 아래와 같이 표시됩니다.