OpenCV3学习笔记——直方图专题2(直方图的绘制)

直方图的绘制——HS直方图和RGB三色直方图

在上一篇博文中我们探讨了直方图的计算,其实直方图可以看成概率密度分布的离散化表达方法,而要注意的是:二维直方图并不是一个通道一个通道的分别独立平行计算,而是将两个通道的数据整合起来计算出的二维直方图

1.1绘制直方图所需要掌握的一些基本函数:

split()和merge()          //颜色通道的分离与合并
line()                          //画线的函数
rectangle()                 //画矩形的函数
normalized()              //归一化函数
minMaxLoc()             //找最大最小值的函数

1.2绘制H-S直方图

图像的HSV表示呢,H通道代表了色调,S通道代表了饱和度,V通道代表了明度
H的范围大概是0-180,S的范围大概是0-255,V的范围大概是0-255
在这里插入图片描述
要画H-S直方图,我们当然得先把原图像转化为HSV模型,用到颜色空间转化函数cvtColor():

cvtColor(scrimage, HSV_image, COLOR_BGR2HSV);

然后对于直方图的计算,请移步至我的上一篇博客:
https://blog.csdn.net/weixin_44586473/article/details/95614238
OpenCV3学习笔记——直方图专题1(直方图的概念以及计算)

好的,我们下面开始画图:
我们先找到直方图的binvalue的最大值:

double max_value = 0;
minMaxLoc(hist_image, 0, &max_value, 0, 0);

由于直方图的最大值可能比较大,我们的画布,图像等也要有一个放大的比例scale:

int scale = 10;   //定义比例为10

下一步开始创建画布:(我们创建一个全0矩阵)

Mat histImage = Mat::zero(hue_bins*scale,sat_bins*scale, CV_8UC3);
//假定hue_bins,sat_bins等变量在之前已经被定义

然后我们就可以开始绘制了(注意:我们计算的特征有几个,就有几个for循环)

for(int i = 0; i < hue_bins; i++)
{
    for(j = 0; j < sat_bins; j++)
    {
        float binvalue = hist_image.at<float>(i, j);    //hist_image已经在计算直方图中定义了
        int intensity = cvRound(binvalue*255/max_value);  //强度
        rectangle(histImage, Point(i*scale, j*scale), Point((i+1)*scale, (j+1)*scale), Scalar::all(intensity),CV_FILLED);   //它是一行一行画的,CV_FILLED是填充矩形
    }
}

来看看效果:
在这里插入图片描述
在这里插入图片描述
对于RGB三色直方图,绘制过程和原理和H-S直方图类似,只不过我们需要用split()函数将原图像的三个颜色通道分离,然后对每个通道单独计算直方图并且分别绘制,下面我直接上代码:

int main()
{
     Mat src, dst ;
     src = imread( "风景.jpg");
     imshow("原始图" , src);
     vector<Mat> rgb_planes;
     split( src, rgb_planes );
     int histSize = 255;
     float range[] = { 0, 255 } ;  //设置变化范围为0-255
     const float* histRange = { range };  //这个将要作为第八个参数,它是每一个维度(特征)的范围组成的阵列
     bool uniform = true; bool accumulate = false;
     Mat r_hist, g_hist, b_hist;
     /// 计算直方图:
     calcHist( &rgb_planes[0], 1, 0, Mat(), r_hist, 1, &histSize, &histRange, uniform, accumulate );//第一个参数是输入数组的地址 , 第二个参数是数组个数 第六个参数因为我们只统计了一个特征所以维度是1
     calcHist( &rgb_planes[1], 1, 0, Mat(), g_hist, 1, &histSize, &histRange, uniform, accumulate );
     calcHist( &rgb_planes[2], 1, 0, Mat(), b_hist, 1, &histSize, &histRange, uniform, accumulate );
     // 创建直方图画布
     int hist_w = 400; int hist_h = 400;
     int bin_w = cvRound( (double) hist_w/histSize );

     Mat histImage( hist_w, hist_h, CV_8UC3, Scalar( 0,0,0) );
     /// 将直方图归一化到范围 [ 0, histImage.rows ]
    normalize(r_hist, r_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(g_hist, g_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );
    normalize(b_hist, b_hist, 0, histImage.rows, NORM_MINMAX, -1, Mat() );

    for( int i = 1; i < histSize; i++ )    //遍历每一个bins, 注意如果是二位直方图就要对每一个特征的bins循环
    {
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(r_hist.at<float>(i-1)) ) ,
        Point( bin_w*(i), hist_h - cvRound(r_hist.at<float>(i)) )
        Scalar( 0, 0, 255), 2, 8, 0  );
        
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(g_hist.at<float>(i-1)) ) ,
        Point( bin_w*(i), hist_h - cvRound(g_hist.at<float>(i)) ),
        Scalar( 0, 255, 0), 2, 8, 0  );
        
        line( histImage, Point( bin_w*(i-1), hist_h - cvRound(b_hist.at<float>(i-1)) ) ,
        Point( bin_w*(i), hist_h - cvRound(b_hist.at<float>(i)) ),
        Scalar( 255, 0, 0), 2, 8, 0  );
    }

     namedWindow("calcHist Demo", CV_WINDOW_AUTOSIZE );
     imshow("calcHist Demo", histImage );
     waitKey(0);
}

我们来看看效果图:
在这里插入图片描述
在这里插入图片描述
好啦,直方图的绘制就先告一段落啦,下一篇博文中我将记录一下直方图的应用——直方图归一化,直方图的对比

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值