直方图就是一种照片的分析方式,横向代表亮度,纵向代表像素数量。首先分析出照片中所有像素的亮度,然后计算出具体数值,再把它们映射到横轴上。这样的话,越高,这个亮度上的像素就越多。
直方图的观看规则就是“左黑右白”,左边代表暗部,右边代表亮部,而中间则代表中间调。纵向上的高度代表像素密集程度,越高,代表的就是分布在这个亮度上的像素很多。
#include <iostream> #include "opencv2/core/core.hpp" #include "opencv2/imgproc/imgproc.hpp" #include "opencv2/highgui/highgui.hpp" using namespace cv; 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;//默认情况,我们考察0号通道 } cv::MatND getHistogram(const cv::Mat &image) { cv::MatND hist; //计算直方图 calcHist(&image,1,channels,cv::Mat(),hist,1,histSize,ranges); return hist; } //计算1D直方图,并返回图像 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 histImage(histSize[0],histSize[0],CV_8U,cv::Scalar(255)); //设置最高点为nbins的90% 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(histImage,cv::Point(h,histSize[0]),cv::Point(h,histSize[0]-intensity),cv::Scalar::all(0)); } return histImage; } }; int main() { cv:: Mat src; src=cv::imread("1.bmp"); //对象 Histogram1D h; //计算直方图 cv::MatND histo=h.getHistogram(src); for(int i=0;i<256;i++) cout<<"Value"<<i<<"="<<histo.at<float>(i)<<endl; //显示直方图 cv::imshow( "直方图",h.getHistogramImage(src)); cv::waitKey(); }