OpenCV学习---绘制直方图(一维、H-S、RGB)

xiaoxiao2021-02-27  354

直方图

简单的说,直方图就是对数据进行统计,将统计值组织到一系列的事先定义好的的 bin 中, bin 的数据是从数据中计算出的特征统计量,这些数据可以是梯度,方向,色彩,或者其它特征。无论如何,直方图获得的是数据分布的统计图。我们最常见的是灰度直方图,也就是统计一副图片中,灰度值的分布情况。

假设有如下的矩阵包含一张8位的灰度图像(0-255)

我们可以对矩阵中的灰度值分布进行统计。首先,我们需要把0-255分成 17 个 区域(bin),如下图所示:

我们对每个范围中的灰度值进行统计排序,做出如下的表格:

我们是以图像的灰度为例子说明这个直方图,当然直方图不仅仅用于灰度特种统计排序,还可以用于图像的梯度、方向等特征。

在以上的过程中,我们使用到一些重要的参数,理解这些参数帮助我们更好的使用API函数。

dims:需要统计的特征的数目,我们上面只统计了 灰度值这个特征,所以, dims =1;

bin :每个特征子区段的数目,上面我们是分成17 个子区段,每个是16个数目,所以,bin =16;

range:每个特征的范围,在上面的例子中,range =  [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 );

绘制图像的一维直方图

int main() { //Load and show image Mat src; src = imread("D:/Lena.jpg"); if (!src.data) { cout<<"Picture loading failed !"<<endl; return -1; } //Transform gray scale image cvtColor(src,src,COLOR_BGR2GRAY); // define parameter int channels = 0; Mat histImage; int dims =1; float hrange[] = {0,255}; const float *range[] = {hrange}; int size = 256; calcHist(&src,1,&channels,Mat(),histImage,dims,&size,range,true,false); Mat dstImage(size,size,CV_8UC3,Scalar(0,0,0)); // get minimum double maxValue =0; minMaxLoc(histImage,0,&maxValue,0,0); for (int i=1;i<size;i++) { float binValue = histImage.at<float>(i); //直方图的背景图像的高度是256,但是图像显示一般是在北京的中间比较好, //所以把图像的像素归一化为 cvRound(250*0.9) = 230; //这样,最大灰度值得统计数目也在就是在(256-230)位置,在图像的中心上下, int value = cvRound(binValue*256*0.9/maxValue); rectangle(dstImage,Point((i-1),size-1),Point(i, size-value),Scalar(255)); } namedWindow("Win2"); imshow("Win2",dstImage); waitKey(0); return 0; }

绘制图像的H-S直方图

绘制图像的RGB通道直方图

int main() { //------------------------读取图像------------------------// Mat src, dst; src = imread("D:/mogu.jpg"); if (!src.data) { cout<<"Picture loading failed !"<<endl; return -1; } namedWindow("Win1"); imshow("Win1",src); //------------------------图像通道的分隔------------------------// vector<Mat> rgb_channel; split(src, rgb_channel); //------------------------计算直方图----------------------------// int histsize =256; float range[] = {0,256}; const float* histRange = {range}; Mat r_Hist,g_Hist,b_Hist; calcHist(&rgb_channel[0],1,0,Mat(),b_Hist,1,&histsize,&histRange,true,false); calcHist(&rgb_channel[1],1,0,Mat(),g_Hist,1,&histsize,&histRange,true,false); calcHist(&rgb_channel[2],1,0,Mat(),r_Hist,1,&histsize,&histRange,true,false); namedWindow("Win3"); imshow("Win3",b_Hist); //------------------------归一化----------------------------// int hist_h = 400; int hist_w = 768; int bin_w =hist_w / histsize; normalize(b_Hist,b_Hist,0,hist_h,NORM_MINMAX,-1,Mat()); normalize(g_Hist,g_Hist,0,hist_h,NORM_MINMAX,-1,Mat()); normalize(r_Hist,r_Hist,0,hist_h,NORM_MINMAX,-1,Mat()); //------------------------画直方图----------------------------// Mat histImage(hist_h,hist_w,CV_8UC3,Scalar(0,0,0)); for (int i = 1; i<histsize; i++) { // draw rectangle rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(b_Hist.at<float>(i))), Scalar(255,0,0)); rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(g_Hist.at<float>(i))), Scalar(0,255,0)); rectangle(histImage, Point(((i-1)*bin_w),hist_h),Point((i*bin_w),hist_h - cvRound(r_Hist.at<float>(i))), Scalar(0,0,255)); } namedWindow("Win2"); imshow("Win2",histImage); waitKey(0); return 0; }

转载请注明原文地址: https://www.6miu.com/read-1580.html

最新回复(0)