直方图

标签: opencv
3人阅读 评论(0) 收藏 举报
分类:

一、图像直方图的概念

图像直方图是反映一个图像像素分布的统计表,其实横坐标代表了图像像素的种类,可以是灰度的,也可以是彩色的。纵坐标代表了每一种颜色值在图像中的像素总数或者占所有像素个数的百分比。图像是由像素构成,因为反映像素分布的直方图往往可以作为图像一个很重要的特征。在实际工程中,图像直方图在特征提取、图像匹配等方面都有很好的应用。

二、利用OpenCV计算图像的直方图

2.1 函数calcHist

OpenCV中计算图像直方图像函数是calcHist,它的参数比较多,下面分析一下它的接口和用法。

函数原型:
void calcHist(const Mat* images, int nimages, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, booluniform=true, bool accumulate=false )
输入参数:
const Mat* images:为输入图像的指针。
int nimages:要计算直方图的图像的个数。此函数可以为多图像求直方图,我们通常情况下都只作用于单一图像,所以通常nimages=1。
const int* channels:图像的通道,它是一个数组,如果是灰度图像则channels={0};如果是彩色图像则channels={0,1,2};如果是只是求彩色图像第2个通道的直方图,则channels={1};
IuputArray mask:是一个遮罩图像用于确定哪些点参与计算,实际应用中是个很好的参数,默认情况我们都设置为一个空图像,即:Mat()。
OutArray hist:计算得到的直方图
int dims:得到的直方图的维数,灰度图像为1维,彩色图像为3维。
const int* histSize:直方图横坐标的区间数。如果是10,则它会横坐标分为10份,然后统计每个区间的像素点总和。
const float** ranges:这是一个二维数组,用来指出每个区间的范围。
后面两个参数都有默认值,uniform参数表明直方图是否等距,最后一个参数与多图像下直方图的显示与存储有关。

举例:

(1)计算灰度图像的直方图

int main()
{
    Mat Image=imread("../cat.png");
    cvtColor(Image,Image,CV_BGR2GRAY);
 
    const int channels[1]={0};
    const int histSize[1]={256};
    float hranges[2]={0,255};
    const float* ranges[1]={hranges};
    MatND hist;
    calcHist(&Image,1,channels,Mat(),hist,1,histSize,ranges);
 
    return 0;
}

(2)计算彩色图像的直方图

int main()
{
    Mat Image=imread("../cat.png");
 
    const int channels[3]={0,1,2};
    const int histSize[3]={256,256,256};
    float hranges[2]={0,255};
    const float* ranges[3]={hranges,hranges,hranges};
    MatND hist;
    calcHist(&Image,1,channels,Mat(),hist,3,histSize,ranges);
 
    return 0;
}

(3)计算灰度图像的不均匀直方图
比如,我们分别统计0-50,50-80,80-150,150-230,230-255区间的灰度分布:
int main()
{
    Mat Image=imread("../cat.png");
    cvtColor(Image,Image,CV_BGR2GRAY);
 
    const int channels[1]={0};
    int histSize[1]={5};
    float hranges[6]={0,50,80,150,230,255};
    const float* ranges[1]={hranges};
 
    MatND hist;
    calcHist(&Image,1,channels,Mat(),hist,1,histSize,ranges,false);
 
    return 0;
}

三、直方图的显示

用calcHist函数计算得到的直方图实际上是一个多维数组,这并不够直观,我们希望能够像在Excel中把相关数据通过表的形式表示出来。下面通过划线函数来把一个灰度直方图显示出来:
Mat getHistImg(const Mat& hist)
{
    double maxVal=0;
    double minVal=0;
 
    //找到直方图中的最大值和最小值
    minMaxLoc(hist,&minVal,&maxVal,0,0);
    int histSize=hist.rows;
    Mat histImg(histSize,histSize,CV_8U,Scalar(255));
    // 设置最大峰值为图像高度的90%
    int hpt=static_cast<int>(0.9*histSize);
 
    for(int h=0;h<histSize;h++)
    {
        float binVal=hist.at<float>(h);
        int intensity=static_cast<int>(binVal*hpt/maxVal);
        line(histImg,Point(h,histSize),Point(h,histSize-intensity),Scalar::all(0));
    }
 
    return histImg;
}

四、直方图变换

图像直方图可以反映出图像对比度,明暗程度等特征,所以我们可以利用直方图的变换进行图像画面的调节。直方图变换在实际工程中的应用很广,一些美化照片的软件很多工具都是在图像的直方图上作文章,对于这这方面的文章作者推荐http://www.cnblogs.com/Imageshop/
下面介绍两个简单的直方图变换函数:直方图拉伸与直方图均衡化。
(1)直方图拉伸
如果图像的灰度在直方图上显示集中在某一个区间,则说明图像色彩单一,我们可以通过直方图拉伸,将其扩展到更宽的灰度范围内让图像更有层次感。
直方图变换的核心就是变换函数,s=T(r),r是变换前的灰度值,s是变换后的灰度值,如要我们想将[a,b]区间的灰度变换到[0,255]范围内,则变换函数是:T(r)=255*(r-a)/(b-a)。
我们在OpenCV中创建这样一个变换函数(其中,minValue和maxValue分别为所选取的图像中的最小灰度与最大灰度):
int imax,imin;
for(imin=0;imin<256;imin++)
{
    if(hist.at<uchar>(imin)>minValue)
        break;
}
for(imax=255;imax>-1;imax--)
{
    if(hist.at<uchar>(imax)>minValue)
        break;
}
// 创建一个1*256的矢量
Mat lut(1,256,CV_8U);
for(int i=0;i<256;i++)
{
    if(lut.at<uchar>(i)<imin)
        lut.at<uchar>(i)=0;
    else if(lut.at<uchar>(i)>imax)
        lut.at<uchar>(i)=255;
    else
        lut.at<uchar>(i)=static_cast<uchar>(
        255.0*(i-imin)/(imax-imin)+0.5);
}

最后我们应用OpenCV中的LUT函数,把直方图拉伸应用在直方图上,即:
LUT(image,lut,result);
其中,函数LUT的第二个参数就像一个查找表一样,将原图像中的灰度按表查找,然后把灰度值替换为表中对应的值。
(2)直方图均衡化
直方图均衡化可以让图像灰度分布更加均匀,让图像的对比度增强。在OpenCV中,有相应的函数equalizeHist直接对图像进行直方图均衡化操作。
int main()
{
    Mat Image=imread("../cat.png");
    cvtColor(Image,Image,CV_BGR2GRAY);


    Mat result;
    equalizeHist(Image,result);


    return 0;
}


查看评论

统计直方图-累加直方图

1  直方图特征:        对颜色特征的表达方式有许多种,我们采用直方图进行特征描述。常见的直方图有两种:统计直方图,累积直方图。我们将分别实验两种直方图在图像聚类和检索中的性能。 ...
  • tkp2014
  • tkp2014
  • 2014-10-16 17:13:19
  • 4208

opencv2 累积直方图

累计直方图代表图像组成成分在灰度级的累计概率分布情况,每一个概率值代表小于等于此灰度值的概率,P(rk)=n1+n2+n3+...Nk。当图像中的特征不能取遍所有可能值时,颜色直方图中会出现很多零值。...
  • lyt1992
  • lyt1992
  • 2015-04-15 10:57:19
  • 1321

OpenCV从入门到放弃(七):直方图那些事儿

图像直方图以及直方图带来的一些算法
  • xierhacker
  • xierhacker
  • 2016-09-25 15:43:03
  • 5854

matlab绘制直方图的方法

直接上代码,利用hist绘制频次直方图和频率直方图。。。%rand Fs=1000;N=10000; t=0:1/Fs:(N-1)/Fs; X1=rand(1,length(t)); subplot(...
  • LG1259156776
  • LG1259156776
  • 2015-09-16 15:45:17
  • 4567

八、matplotlib系列---pyplot直方图的绘制

matplotlib系列—pyplot直方图的绘制pyplot使用plt.hist()来绘制直方图import numpy as np import matplotlib.pyplot as pltn...
  • skyli114
  • skyli114
  • 2017-08-23 17:10:57
  • 556

一段很巧妙的直方图统计算法代码

double absolute_histo[256] = { 0 }; for (int i = 0; i < Image.rows; i++) { const uch...
  • qq_19764963
  • qq_19764963
  • 2016-03-21 14:03:12
  • 1092

直方图理解

灰度直方图是数字图像中最简单且有用的工具,这一篇主要总结OpenCV中直方图CvHistogram的结构和应用。 灰度直方图的定义 a.“图”,横纵坐标的含义 b.灰度级图像的函数 ...
  • sheldonwxp
  • sheldonwxp
  • 2012-06-26 16:46:27
  • 6802

利用JS的D3库实现直方图

D3(Data-Driven Documents)是一个用动态图形显示数据的JavaScript库,一个数据可视化的工具。下面我们用D3 实现了可排序的直方图。 body { ...
  • cloud_post
  • cloud_post
  • 2015-06-12 18:12:57
  • 1389

直方图统计的FPGA实现

直方图统计是图像处理算法中最基本和常见的算法之一,主要原理就是将图像中各个灰度级的像素个数进行计算并统计,这在一些对灰度特性进行统计的算法中比较常见。虽然直方图统计在MATLAB或软件中耗时也很少,但...
  • calorie6677
  • calorie6677
  • 2016-03-04 16:17:34
  • 1479

基于直方图的特征-----经典的SIFT特征

author:liumm 时间:2014/7/29-------
  • only444572170
  • only444572170
  • 2014-07-29 09:20:07
  • 1139
    个人资料
    持之以恒
    等级:
    访问量: 2万+
    积分: 564
    排名: 9万+
    最新评论