히스토그램이란?
이미지에서 픽셀들이 가지는 값들의 출현빈도를 히스토그램이라한다.
GRAY이미지에서는 0~255값을 가진다.
이미지의 크기를 400 x 400이라고 한다면, 총 160,000개의 픽셀들을 0 ~ 255값에 따라 분류하여
각 개별값을 갖는 픽셀들이 몇개인지 알아낸 것이 히스토그램이다.
calcHist()
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
);
images : 대상 이미지
nimages : 배열에 포함된 이미지의 개수
channels : Histogram을 계산할 채널 번호의 배열.
예를 들어 아래 그림과 같이 BGR이미지 2장에 대해, img1은 B채널, img2는 G채널에 대해서 히스토그램을 구하고자 한다면 {0,4}를 배열에 넣어 전달해야한다.
mask : 히스토그램을 계산할 영역을 지정할 수 있다. Mat()을 전달하면 아무것도 하지않는다.
hist : 히스토그램을 계산한 결과를 저장한다.
dims : 히스토그램 계산 결과를 저장한 hist의 차원
histSize : 빈도수를 분류할 칸의 개수
ranges : 각 차원의 분류 bin의 최소, 최대값을 의미한다.
minMaxLoc()
배열에서 가장 큰값과 작은 값을 찾는 함수
- C++ :
- void
minMaxLoc
( - InputArray src,
- double* minVal,
- double* maxVal=0,
- Point* minLoc=0,
- Point* maxLoc=0,
- )
코드
#include<iostream>
#include<opencv2\core.hpp>
#include<opencv\cv.h>
#include<opencv2\highgui.hpp>
#include<opencv2\imgproc.hpp>
using namespace cv;
int histSize[1];
float hranges[2];
const float* ranges[1];
int channels[1];
MatND getHistogram(const Mat &image) {
histSize[0] = 256;
hranges[0] = 0.0; //히스토그램 최소 값
hranges[1] = 255.0; //히스토그램 최대 값
ranges[0] = hranges;
channels[0] = 0;
MatND hist;
calcHist(&image, 1, channels, Mat(), hist, 1, histSize, ranges);
return hist;
}
Mat getHistogramImage(const Mat &image) {
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 255.0;
ranges[0] = hranges;
channels[0] = 0;
// 만약 BGR값을 위한 히스토 그램을 만들고 싶다면,
// channels[0] = {0}; //blue
// channels[0] = {1}; //green
// channels[0] = {2}; //red 를 해주면된다.
MatND hist = getHistogram(image); // 히스토그램 계산
double maxVal = 0; // 최대 빈도수
double minVal = 0; // 최소 빈도수
minMaxLoc(hist, &minVal, &maxVal, 0, 0);
Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));
int hpt = static_cast<int>(0.9*histSize[0]);
//그래프 그리기
for (int h = 0; h < histSize[0]; h++) {
float binVal = hist.at<float>(h);
int intensity = static_cast<int> (binVal*hpt / maxVal);
line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));
}
return histImg;
}
int main() {
Mat image = imread("image/humming_bird.jpg", 0);
Mat thresholded;
Mat eqHist;
if (!image.data)
{
std::cout << "open failed" << std::endl;
return 0;
}
//원본
namedWindow("Image");
imshow("Image", image);
//원본 히스토그램
MatND histo = getHistogram(image);
namedWindow("Histogram");
imshow("Histogram", getHistogramImage(image));
//히스토그램 이퀄라이제이션한 영상
equalizeHist(image, eqHist);
imshow("Image_EQ", eqHist);
//imwrite시에 영상의 퀄리티 정도를 지정해줄수있다.
imwrite("Image_Histogram EQ.jpg", eqHist, { CV_IMWRITE_JPEG_QUALITY , 50 });
//히스토그램 이퀄라이제이션 히스토그램 출력
imshow("Histogram_EQ", getHistogramImage(eqHist));
//영상 이진화
threshold(image, thresholded, 100, 255, THRESH_BINARY);
namedWindow("Binary Image");
imshow("Binary Image", thresholded);
imwrite("Image_Histogram threshold.jpg", thresholded, { CV_IMWRITE_JPEG_QUALITY , 50});
waitKey(0);
return 0;
}
결과 영상