1. 히스토그램 스트레칭
히스토그램 스트레칭
- 영상의 히스토그램이 그레이스케일 전 구간에서 걸쳐 나타나도록 변경하는 선형변환 기법
- 특정구간에 집중되어 나타나는 히스토그램을 마치 고무줄을 늘이듯 펼쳐서 그레이스케일 범위 전 구간에서 히스토그램이 골고루 나타나도록 변환
변환 함수의 직선의방정식 구하기
- 기울기: 255 / (Gmax - Gmin)
- y절편: 255xGmin / Gmax - Gmin
실습코드
int main()
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return -1;
}
double gmin, gmax;
minMaxLoc(src, &gmin, &gmax);
Mat dst = (src - gmin) * 255 / (gmax - gmin);
imshow("src", src);
imshow("dst", dst);
waitKey();
}
2. 히스토그램 평활화
히스토그램 평활화란
- 히스토그램이 그레이스케일 전체 구간에서 균일한 분포로 나타나도록 변경하는 명암비 향상기법
평활화 변환함수 구하기
- 히스토그램을 구한다.
- 구한 히스토그램을 정규화 시킨다.
- 누적분포함수(cdf)를 구한다.
- 누적분포함수에 픽셀값의 최댓값을 곱하고 반올림한다.
실습코드
#include <iostream>
#include "opencv2/opencv.hpp"
using namespace std;
using namespace cv;
Mat calcGrayHist(const Mat& img)
{
CV_Assert(img.type() == CV_8UC1);
Mat hist;
int channels[] = { 0 };
int dims = 1;
const int histSize[] = { 256 };
float graylevel[] = { 0, 256 };
const float* ranges[] = { graylevel };
calcHist(&img, 1, channels, noArray(), hist, dims, histSize, ranges, true);
return hist;
}
Mat histImage(const Mat& hist)
{
CV_Assert(!hist.empty());
CV_Assert(hist.type() == CV_32FC1);
CV_Assert(hist.size() == Size(1, 256));
double histMax = 0.;
minMaxLoc(hist, 0, &histMax);
Mat imgHist(100, 256, CV_8U, 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;
}
int main(int argc, char* argv[])
{
Mat src = imread("lenna.bmp", IMREAD_GRAYSCALE);
if (src.empty()) {
cerr << "Image load failed!" << endl;
return -1;
}
Mat dst(src.rows, src.cols, src.type());
#if 1
equalizeHist(src, dst);
#else
int hist[256] = { 0, };
for (int j = 0; j < src.rows; j++)
for (int i = 0; i < src.cols; i++)
hist[src.at<uchar>(j, i)]++;
int size = (int)src.total();
float cdf[256] = { 0.0f, };
cdf[0] = float(hist[0]) / size;
for (int i = 1; i < 256; i++)
cdf[i] = cdf[i - 1] + float(hist[i]) / size;
for (int j = 0; j < src.rows; j++) {
for (int i = 0; i < src.cols; i++) {
dst.at<uchar>(j, i) = uchar(cdf[src.at<uchar>(j, i)] * 255);
}
}
#endif
imshow("src", src);
imshow("dst", dst);
imshow("hist_src", histImage(calcGrayHist(src)));
imshow("hist_dst", histImage(calcGrayHist(dst)));
waitKey();
}
히스토그램 스트레칭과 평활화 결과 비교