1.一些小概念:
(1) 像素值在图像中的分布情况是这幅图像的一个重要特征。
(2) 直方图是一个简单的表,它给出了一幅图像或一组图像中用于给定数值的像素数量。
2.calcHist 函数
calHist 是opencv 中可以计算直方图。
private:
int histSize[1];//色度变换宽度
float hranges[2];//像素的最小值及最大值
const float * ranges[1];//
int channels[1];//使用的通道
public:
Histogram1D(){
histSize[0] = 256;
hranges[0] = 0.0;
hranges[1] = 255.0;
ranges[0] = hranges;
channels[0] = 0;
}
cv::MatND getHistogram(const cv::Mat &image){
cv::MatND hist;
cv::calcHist(&image,1,channels,cv::Mat(),hist,1,histSize,ranges);
return hist;
}
下面给出对一个具体图像求出直方图的例子
#include <opencv2\core\core.hpp>
#include <opencv2\imgproc\imgproc.hpp>
#include "cv.h"
#include "highgui.h"
#include <iostream>
using namespace std;
class Histogram1D {
private:
int histSize[1];
float hranges[2];
const float* ranges[1];
int channels[1];
public:
Histogram1D() {
histSize[0]= 256;
hranges[0]= 0.0;
hranges[1]= 255.0;
ranges[0]= hranges;
channels[0]= 0;
}
cv::MatND getHistogram(const cv::Mat &image) {
cv::MatND hist;
cv::calcHist(&image, //目标图像
1, // 计算一张直方图
channels, // 使用的通道数量
cv::Mat(), // 图像开关
hist, // 返回的直方图
1, // 1D直方图
histSize, // 色图宽度
ranges // 像素值的范围
);
return hist;
}
cv::Mat getHistogramImage(const cv::Mat &image){
cv::MatND hist= getHistogram(image);
double maxVal=0;
double minVal=0;
cv::minMaxLoc(hist, &minVal, &maxVal, 0, 0);
cv::Mat histImg(histSize[0], histSize[0], CV_8U,cv::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);
cv::line(histImg,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0));
}
return histImg;
}
};
int main()
{
cv::Mat image= cv::imread("group.jpg",0);
if (!image.data)
return 0;
cv::namedWindow("Image");
cv::imshow("Image",image);
Histogram1D h;
cv::MatND histo= h.getHistogram(image);
for (int i=0; i<256; i++)
cout << "Value " << i << " = " << histo.at<float>(i) << endl;
cv::namedWindow("Histogram");
cv::imshow("Histogram",h.getHistogramImage(image));
cv::waitKey();
return 0;
}
输出结果