히스토그램은 픽셀값(또는 픽셀범위)마다 해당하는 픽셀의 개수를 세고, 이를 그래프로 표현한 것입니다. 아래는 히스토그램 및 히스토그램 스트레칭, 히스토그램 평활화에 대한 간단한 예제코드입니다. 히스토그램 스트레칭과 히스토그램 평활화는 영상의 히스토그램 전 영역에 골고루 나타나도록 변경하는 알고리즘입니다.
예제 코드
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
// 히스토그램 연산 수행
Mat calc8UC1Hist(Mat& img);
// 히스토그램 연산 수행 결과를 입력으로 히스토그램 그리기
Mat get8UC1HistImage(Mat& hist);
// 히스토그램 스트레칭 수행
Mat histogramStretching(Mat& img);
int main()
{
// 원본이미지
Mat img = imread("lenahisto.bmp", IMREAD_GRAYSCALE);
Mat hist1 = calc8UC1Hist(img);
Mat hist_org_img = get8UC1HistImage(hist1);
// 원본이미지에 히스토그램 스트레칭
Mat hist_stretched = histogramStretching(img);
Mat hist2 = calc8UC1Hist(hist_stretched);
Mat hist_stretched_img = get8UC1HistImage(hist2);
// 원본이미지에 히스토그램 평활화(=평탄화, Equalization)
Mat equal_img;
equalizeHist(img, equal_img);
Mat hist3 = calc8UC1Hist(equal_img);
Mat hist_equalize_img = get8UC1HistImage(hist3);
imshow("ori", img);
imshow("org_hist", hist_org_img);
imshow("stretch", hist_stretched);
imshow("streched_hist", hist_stretched_img);
imshow("equalize", hist_stretched);
imshow("equlized_hist", hist_stretched_img);
waitKey();
destroyAllWindows();
return 0;
}
Mat calc8UC1Hist(Mat& img)
{
CV_Assert(img.type() == CV_8UC1);
Mat hist;
int channels[] = { 0, };
int dims = 1;
const int histSize[] = { 256 };
float level[] = { 0, 256 };
const float* ranges[] = { level };
calcHist(&img, 1, channels, noArray(), hist, dims, histSize, ranges);
return hist;
}
Mat get8UC1HistImage(Mat &hist)
{
CV_Assert(hist.type() == CV_32FC1);
CV_Assert(hist.size() == Size(1, 256));
double histMax;
minMaxLoc(hist, 0, &histMax);
Mat imgHist(100, 256, CV_8UC1, Scalar(255));
for (int i=0 ; i<256 ; i++)
{
line(imgHist,
Point(i, 100),
Point(i, 100-cvRound(hist.at <float>(i) * 100 / histMax)),
Scalar(0));
}
return imgHist;
}
Mat histogramStretching(Mat& img)
{
double min_val, max_val;
minMaxLoc(img, &min_val, &max_val);
return (img - min_val) * 255 / (max_val - min_val);
}
실행 결과
왼쪽부터 원본 영상, 히스토그램 스트레칭 영상, 히스토그램 평활화(Equalization) 영상입니다.