图像处理中的灰度直方图

2013-10-20 15:47:34 thnh169 阅读数 12367
  • 图像直方图统计

    掌握OpenCV核心模块,熟练使用相关API 理解各个API背后的相关算法原理,每个参数意义 有能力解决使用应用场景问题,大量工程代码经验分享 掌握图像处理与视频分析,图像分析与测量编码与开发技巧

    159人学习 贾志刚
    免费试看

直方图均衡

        一副图像的直方图,表示了其灰度分布的特性。对于数字图像来说,假设灰度值k出现了次,那么其概率密度函数如下所示。


这个式子,表示了像素的灰度值为k概率。其中,MN为图像的尺寸。

       对于一幅动态范围较窄的图像,其归一化灰度直方图如下所示。


       对于此类图像,使用灰度拉伸,也能使其的动态范围得到改善,增强图像对比度。但是,灰度拉伸从本质上来讲,是很暧昧的,灰度拉伸没有什么明确的目的,只是依靠某个函数的做了灰度变换,使得图像的在灰度直方图的分布范围扩大。灰度拉伸对于结果没有严格的要求,因此根据变换函数的不同,灰度拉伸有无数种结果。

       与灰度拉伸不同的是,直方图均衡的目的就比较明确,使用某个特殊的函数,使原图像的灰度分布平均化。为了将其平均化,这里需要用到累积分布函数(Probability Density Function的概念。

所谓的平均化,直方图均衡的目的是将一幅图的累积分布的曲线(下图左),变为下图右的分布形式。

    

                                                 (左)原图的累积分布曲线                        (右)理想化直方图均衡后的累积分布曲线

       从右图中可以看出,为了保证直方图均衡后的累积分布曲线是一条倾角为45°的直线,那么,变换后的函数的概率密度函数应与输入值无关,且保持一个常量。输入r与输出s有如下关系,


将变换关系

  

带入上式子,可得


将其带入输入r与输出s关系,可得到


到此,已经可以看出,输出的概率密度函数,与s的取值无关。很明显,这个分布是绝对平均的。

       但是,事实上,上面的式子均是在连续的情况下的。在数字图像的领域,我们必须将其离散化,才能使用。离散的情况下,其累计分布函数如下所示。


至此,直方图均衡就完成了。

       为了验证结果,其直方图均衡后的图像与灰度直方图如下所示。


结果就是这样了。但是,呃!!!!问题来了,这是直方图均衡么?这跟灰度拉升有何区别,而且其均衡后的图像的直方图也不是一个很平均的值,和我们的构想有很大区别。这个结果真的没问么?为了回答这个问题,将其原图像的累积分布函数与直方均衡后的累积分布函数画出来,如下。

                      

                                                      (左)原图的累积分布曲线                                             (右)直方图均衡后的累积分布曲线

从累积分布曲线中,我们可以看到,直方图均衡后的曲线,确实跟我们设想的理想曲线很接近!由于我们证明的时候,是在连续的情况下去思考的,所以,将其离散之后,多少是有不理想的情况发生的。均衡后的累积分布曲线确实是一个不错的结果。这样看来,我们才能看清楚直方图均衡的本质。若不是这样,还真不知道直方均衡与灰度拉伸的区别。

为此,直方图均衡成功,Matlab代码如下。

close all;
clear all;

%% -------------Histogram Equalization-----------------
close all;
clear all;

f = imread('washed_out_pollen_image.tif');
f = mat2gray(f,[0 255]);

[M,N] = size(f);
g = zeros(M,N);

r = imhist(f)/(M*N);  %(500*500 is size of image)
s = zeros(256,1);

for k = 1:1:256
    for j = 1:1:k
        s(k,1) = s(k,1) + r(j);
    end
end

for x = 1:1:M        %(500*500 is size of image)
    for y = 1:1:N
        g(x,y) = s(uint8(f(x,y)*255)+1,1);
    end
end 


figure();
subplot(2,2,1);
imshow(f);
xlabel('a).Original Image');

subplot(2,2,2);
h = imhist(f)/(M*N);
bar(0:1/255:1,h);
axis([0 1 0 0.1]),grid;
%axis square;
xlabel('b).The Histogram of a');
ylabel('Number of pixels');

subplot(2,2,3);
imshow(g);
xlabel('c).Histogram Equalization');

subplot(2,2,4);
h = imhist(g)/(M*N);
bar(0:1/255:1,h);
axis([0 1 0 0.1]),grid;
%axis square;
xlabel('d).The Histogram of c');
ylabel('Number of pixels');

figure();
x=0:1/255:1; 
plot(x,s);
axis([0,1,0,1]),grid;
axis square;
xlabel('intensity level of r');
ylabel('P_{r}(r)');

r = imhist(g)/(M*N);
s = zeros(256,1);
for k = 1:1:256
    for j = 1:1:k
        s(k,1) = s(k,1) + r(j);
    end
end
figure();
x=0:1/255:1; 
plot(x,s);
axis([0,1,0,1]),grid;
axis square;
xlabel('intensity level of s');
ylabel('P_{s}(s)');

(作者注:其实,直方图均衡有直接的函数,这里只是想按照自己理解的方法去做个均衡出来看看,所以高级一点的库函数基本没有,都用循环来的)

直方图匹配

       前面,我们说了直方图的均衡,直方均衡可以得到一个灰度直方图分布平均的图像。但是有一些问题,直方图均衡的结果是唯一的。这是其优点,也是其缺点。优点在于,无需多余的参数,就可以实现对比度的增强。缺点在于,没有参数,对于结果无法调整。举个栗子(输入法君卖萌了╭(╯3╰)╮),一幅很黑的图像,使用直方图均衡的话,这幅图像的直方均衡结果,将使得图像偏白。使用《Digital Image Processing》 Rafael C. Gonzalez / Richard E. Woods 的例子来说,看下图。


       如上图所示,直方均衡的结果不是很理想。由直方均衡的结果看来,我们能看到,其实对比原图,原图一些细节已经显露出来了,只要稍加修改,就可以得到很理想的增强结果。为此,直觉告诉我们(不要吐槽这句话,有时候直觉就是那么简单。\(≧▽≦)/),只需要将原图的灰度直方图稍微左移一些即可。但是,直方均衡却是不可调整的,为此,就有了直方图匹配。

       对于原图像,其概率分布函数是

 

其输出也就是直方均衡的结果。为了实现直方图匹配,我们还需要一个函数,也就是我们所期待的概率分布函数。这个概率分布函数的概率分布函数如下所示。


其中,z代表了期望的分布。我们假设如下关系成立。


也就是,我们所期待的直方图分布的概率分布函数与原图像的直方图概率分布函数相等。那么,我们可以利用G()的反函数,我们也就可以得到我们所期待的直方图。


       上面的描述可能太过拖沓,我们采用简洁一点的描述。

       一. 将原图进行直方图均衡。

       二. 假设我们期待的分布,直方均衡的结果与原图直方图均衡的结果一致。利用反函数,还原成我们期待的分布。

       所实现的直方图均衡结果如下所示。


根据直方图匹配的结果,我们可以看出,所得出的结果和我们所期待的分布很接近。其结果也和我们的初衷一样,使得原图的直方图稍微左移了一些。所得到的结果比起直方均衡要好得多。

其Matlab代码如下。

%% -------------Histogram Matching-----------------
close all;
clear all;

f = imread('mars_moon_phobos.tif');
f = mat2gray(f,[0 255]);

[M,N] = size(f);
g = zeros(M,N);

r = imhist(f)/(M*N); 
s = zeros(256,1);

for k = 1:1:256
    for j = 1:1:k
        s(k,1) = s(k,1) + r(j);
    end
end
 
for x = 1:1:M        
    for y = 1:1:N
        g(x,y) = s(uint8(f(x,y)*255)+1,1);
    end
end 

figure();
subplot(2,2,1);
imshow(f);
xlabel('a).Original Image');

subplot(2,2,2);
h = imhist(f)/(M*N);
bar(0:1/255:1,h);
axis([0 1 0 0.1]),grid;
xlabel('b).The Histogram of a');

subplot(2,2,3);
imshow(g);
xlabel('c).Histogram Equalization');

subplot(2,2,4);
h = imhist(g)/(M*N);
bar(0:1/255:1,h);
axis([0 1 0 0.1]),grid;
xlabel('d).The Histogram of c');

%---------------pz-----------------------
r = r';
p = [0:r(1,1)/15:r(1,1) 17*r(1,2:241)];
%p = [0:r(1,1)/15:r(1,1) r(1,2:241)];
%p = [0:55:255 , 255:-25:24 , 24:-0.14:0 , 0:1:15 , 15:-0.285:0];
p = (p/sum(p));
p = p';
r = r';

G = zeros(256,1);
for k = 1:1:256
    for j = 1:1:k
        G(k,1) = G(k,1) + p(j);
    end
end


G_Negatives = zeros(256,1);
Flag = 0;
for k = 1:1:256
    for j = 1:1:256
            if(uint8(G(j,1)*255) == k) 
                 G_Negatives(k,1) = (j-1)/255;
                 Flag = 1;
            end
    end
    
    if(Flag == 0)
        if(k == 1) G_Negatives(k,1) = 0;
        else G_Negatives(k,1) = G_Negatives(k-1,1); end   
    end
    Flag = 0;

end

z = zeros(M,N);
for x = 1:1:M       
    for y = 1:1:N
        z(x,y) =  G_Negatives(uint8(g(x,y)*255)+1,1);
    end
end 

figure();
subplot(2,2,1);
imshow(z);
xlabel('a).Histogram Matching');

subplot(2,2,2);
h = imhist(z)/(M*N);
bar(0:1/255:1,h);
axis([0 1 0 .1]),grid;
xlabel('b).The Histogram of a');

subplot(2,2,3);
x=0:1/255:1; 
plot(x,p);
axis([0,1,0,.1]),grid;
xlabel('c).Specifieds Histogram (Normalized)');
 
subplot(2,2,4);
x=0:1/255:1; 
plot(x,G,x,G_Negatives);
axis([0,1,0,1]),grid;
axis square;
xlabel('Input intensity level');
ylabel('Onput intensity level');

博客地址:http://blog.csdn.net/thnh169/ 



2017-02-27 20:19:15 u013355826 阅读数 8927
  • 图像直方图统计

    掌握OpenCV核心模块,熟练使用相关API 理解各个API背后的相关算法原理,每个参数意义 有能力解决使用应用场景问题,大量工程代码经验分享 掌握图像处理与视频分析,图像分析与测量编码与开发技巧

    159人学习 贾志刚
    免费试看


——————————————————————————————————————————————



有梦想,那就去坚持去做,坚持去完成第一个10000万小时!


——————————————————————————————————————————————


一.什么是直方图

简单的说灰度直方图就是:一幅图像中灰度级与出现这种灰度的概率之间关系的图形,灰度直方图是一种统计表达,反映了不同灰度级出现的统计概率(个数),其横坐标是:灰度级,纵坐标是:出现的个数(概率)。

(1)直方图的离散函数 h(rk)=nk。其中rk是第K级的灰度值,nk是图像中灰度为rk的像素的个数。

(2)归一化直方图 p(rk)=nk/MN。其中k = 0,1,2.....L-1(灰度级的范围是[ 0 , L-1]),MN表示像素的总的个数。


2.直方图修正的应用

直方图的修正是以概率论为基础,常用的方法有:直方图均衡化、直方图匹配(规定化)、局部直方图处理。


3.直方图均衡化的背景

在图像处理的过程中,我们注意到:

(1)在暗的图像中,直方图的灰度量集中在灰度级比较低(灰度值比较小)的那一端。如图 a 所示。

(2)在亮的图像中,直方图的灰度量集中在灰度级比较高(灰度值比较大)的那一端。如图 b 所示。

(3)在低对比度的图像中,直方图的灰度量具有较窄的范围,并且集中在灰度级的中部,如图 c 所示。

(4) 在高对比度的图像中,直方图的灰度量具有较宽的范围,并且像素分布比较均匀,如图 d 所示。

图a图b图c图d

如果一幅图像的像素倾向于占据整个可能的灰度级并且分布均匀,则该图像有较高的对比度,并展示色调的变化很大。最终的效果就是一幅灰度细节丰富且动态范围较宽的图像。我们需要仅仅依靠输入图像的直方图的可用信息开发出 一个变换函数来自动的实现这种效果。由此我们引出了直方图的均衡化。


二.直方图均衡化

基本思想:把原图像变换为在整个灰度范围内均匀分布的形式。

目的:寻找一个变换函数实现输出图像的灰度值能够在整个范围内均匀分布。

考虑连续的灰度值,用变量 r 表示输入图像的灰度,用 s 表示输出图像的灰度。r 范围是 [ 0, L-1],则函数:

     s = T(r), r 的范围:[0 , L-1] 

T(r) 满足的条件:

(1)T(r) 在区间[0 , L-1] 严格单调递增函数。

 这个条件保证了输入图像灰度值高的地方,输出图像的灰度值也高,不会对原图像的性质反生改变。

(2)当 r 的范围:[0 , L-1] 时,T(r) 也在[0 , L-1]内。 

这个条件保证原图像和新图像的灰度值范围一致。

 我们需要引入。这种情况下,T(r)在区间是一个严格单调函数。

在图像处理中,特别重要的变换函数如下形式:

    

这个函数遵循条件1和条件2。

一幅图像看做是区间 [0,L-1] 的随机变量。看做随机变量  r 和 s 的概率密度函数。

由概率论定理知:


得到图像变换后的 s 的PDF



对变换函数两边对 r 求导数


把  ds/dr 结果带入变量 s 的PDF函数,得到


 

得到ps(s)是一个均匀的概率密度函数,与pr(r)无关。

(2)离散变换


这样,输出的图像通过 T( rk )将输入的灰度级 rk ,映射到输出图像中灰度级为 sk对应的像素得到。

例子:



输出图形的灰度是sk(K=0,1.2,....7)。


s 值一直是分数,因此我们要近似为整数:

s0 = 1.33≈1 ;s1 =3.08≈3 ;s2= 4.05≈4 ;s3 = 5.67≈6 s4 =6.23≈6 ;s5 = 6.66≈7s6= 6.86≈7 ;s7 = 7.00≈7 ;

均衡后得到新的灰度值sk与像素点个数。



三.直方图匹配(规定化)

直方图的均衡化是自动挡额确定变换函数,该函数寻求产生有均匀直方图的输出图像。有时候,我们希望处理后的图像具有规定的直方图形状,这种用于产生处理后的有特殊直方图的方法称为直方图匹配或者直方图规定化。

 

令 s  为一个有如下特性的随机变量:


接着我们假设有如下性质的 z 变量


由这两个等式可得 G(z) = T(r),因此,z 满足


直方图的规定化在原理上是简单的,但是实践中,共同的困难就是寻找 T(r) 和 G反函数有意义的表达式。幸运的是,在处理离散量时,问题可以大大的简化。

离散形式直方图规定化过程

(1)由给定图像的直方图pr(r),并寻找直方图的均衡变换。并把 sk 四舍五入到范围 [0, L-1]内的整数。

(2)根据,求得变换函数 G 的值,其中pz(zi)是规定的直方图的值。把G 的值四舍五入到范围 [0, L-1]内的整数。

(3)对于每一个值Sk,使用②存储的值寻找相应的Zq值,使G(Zq)最接近Sk,并存储这些从S到Z的映射。 

例题
















2016-05-17 11:04:38 boon_228 阅读数 9487
  • 图像直方图统计

    掌握OpenCV核心模块,熟练使用相关API 理解各个API背后的相关算法原理,每个参数意义 有能力解决使用应用场景问题,大量工程代码经验分享 掌握图像处理与视频分析,图像分析与测量编码与开发技巧

    159人学习 贾志刚
    免费试看

1灰度直方图

       1.1 概念

灰度直方图是关于灰度级分布的函数,是对图像中灰度级分布的统计。

灰度直方图是将数字图像中的所有像素,按照灰度值的大小,统计其出现的频率。

灰度直方图是灰度级的函数,它表示图像中具有某种灰度级的像素的个数,反映了图像中某种灰度出现的频率。
  
如果将图像总像素亮度(灰度级别)看成是一个随机变量,则其分布情况就反映了图像的统计特性,这可用probability density function (PDF)来刻画和描述,表现为灰度直方图。

       1.2 opencv表示
       opencv提供了calcHist函数来计算图像直方图。

         其中C++的函数原型如下:

void calcHist(const Mat* arrays, int narrays, const int* channels, InputArray mask, OutputArray hist, int dims, const int* histSize, const float** ranges, bool uniform=true, bool accumulate=false );

         参数解释:

        arrays:输入的图像的指针,可以是多幅图像,所有的图像必须有同样的深度(CV_8U or CV_32F)。同时一副图像可以有多个channes。

        narrays:输入的图像的个数。

        channels:用来计算直方图的channes的数组。比如输入是2副图像,第一副图像有0,1,2共三个channel,第二幅图像只有0一个channel,那么输入就一共有4个channes,如果int channels[3] = {3, 2, 0},那么就表示是使用第二副图像的第一个通道和第一副图像的第2和第0个通道来计算直方图。

        mask:掩码。如果mask不为空,那么它必须是一个8位(CV_8U)的数组,并且它的大小的和arrays[i]的大小相同,值为1的点将用来计算直方图。

        hist:计算出来的直方图

        dims:计算出来的直方图的维数。

        histSize:在每一维上直方图的个数。简单把直方图看作一个一个的竖条的话,就是每一维上竖条的个数。

        ranges:用来进行统计的范围。比如 float rang1[] = {0, 20}; float rang2[] = {30, 40};  const float *rangs[] = {rang1, rang2};那么就是对0,20和30,40范围的值进行统计。

       uniform:每一个竖条的宽度是否相等。

       accumulate:  是否累加。如果为true,在下次计算的时候不会首先清空hist。


2 直方图均衡化

      1.1 概念

          如果一副图像的像素占有很多的灰度级而且分布均匀,那么这样的图像往往有高对比度和多变的灰度色调。

         直方图均衡化就是一种能仅靠输入图像直方图信息自动达到这种效果的变换函数。

         它的基本思想是对图像中像素个数多的灰度级进行展宽,而对图像中像素个数少的灰度进行压缩,从而扩展像原取值的动态范围,提高了对比度和灰度色调的变化,使图像更加清晰。

        直方图均衡化处理的“中心思想”是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。

        直方图均衡化的基本思想是把原始图的直方图变换为均匀分布的形式,这样就增加了像素灰度值的动态范围从而可达到增强图像整体对比度的效果。

    2.2 opencv表示

               cv::equalizeHist(img_gray,equalize_Hist)


3.例程

int img_Hist(Mat& image)
{
    if(!image.data)
    {
        cout << "fail to load image" << endl;
        return 0;
    }
    Mat img_gray;
    //GRAY
    if(image.channels()==3)
    {
    	cvtColor(image, img_gray, CV_BGR2GRAY);
    }
    else
    {
    	image.copyTo(img_gray);
    }
    cv::imwrite("img_gray.jpg",img_gray);

    MatND hist;       // 在cv中用CvHistogram *hist = cvCreateHist
    int dims = 1;
    float hranges[] = {0, 255};
    const float *ranges[] = {hranges};   // 这里需要为const类型
    int size = 256;
    int channels = 0;
    // 计算图像的直方图
    calcHist(&img_gray, 1, &channels, Mat(), hist, dims, &size, ranges);    // cv 中是cvCalcHist
    int scale = 1;
    Mat imageShow(size * scale, size, CV_8U, Scalar(0));
    // 获取最大值和最小值
    double minVal = 0;
    double maxVal = 0;
    minMaxLoc(hist,&minVal, &maxVal, 0, 0);  //  cv中用的是cvGetMinMaxHistValue
    //显示直方图的图像
    int hpt = saturate_cast<int>(0.9 * size);

    for(int i = 0; i < 256; i++)
    {
        float value = hist.at<float>(i);           //   注意hist中是float类型    cv中用cvQueryHistValue_1D
        int realValue = saturate_cast<int>(value * hpt/maxVal);
        rectangle(imageShow,Point(i*scale, size - 1), Point((i+1)*scale - 1, size - realValue), Scalar(255));
    }
    namedWindow("Hist");
    imshow("Hist", imageShow);
    cv::imwrite("hist.jpg",imageShow);
    Mat equalize_Hist;
    cv::equalizeHist(img_gray,equalize_Hist);

    namedWindow("equalize_Hist");
    imshow("equalize_Hist", equalize_Hist);
    cv::imwrite("equalize_Hist.jpg",equalize_Hist);
    // 计算图像的直方图
       calcHist(&equalize_Hist, 1, &channels, Mat(), hist, dims, &size, ranges);    // cv 中是cvCalcHist
       Mat imageShow_equal(size * scale, size, CV_8U, Scalar(0));
       // 获取最大值和最小值
       minMaxLoc(hist,&minVal, &maxVal, 0, 0);  //  cv中用的是cvGetMinMaxHistValue
       //显示直方图的图像
       hpt = saturate_cast<int>(0.9 * size);
       for(int i = 0; i < 256; i++)
       {
           float value = hist.at<float>(i);           //   注意hist中是float类型    cv中用cvQueryHistValue_1D
           int realValue = saturate_cast<int>(value * hpt/maxVal);
           rectangle(imageShow_equal,Point(i*scale, size - 1), Point((i+1)*scale - 1, size - realValue), Scalar(255));
       }

       namedWindow("Hist_equalize");
       imshow("Hist_equalize", imageShow_equal);
       cv::imwrite("Hist_equalize.jpg",imageShow_equal);
    waitKey(0);
    return 0;
}
int main (int args, char** argv)
{
	Mat image = imread("/home/odroid/TEST/111.jpg", 1);    // 这里也可以是BGR 但是想想提取轮廓 效果是一样的
 	imshow("original", image);
 	img_Hist(image);
	waitKey();
    return 0;
}




             
        
                            原始图                                                                                                                       灰度图
                                                                           
灰度直方图                                                                                                                             均衡化后的灰度直方图
                                                                    
                        直方图均衡化后的灰度图


          
       
2018-02-05 00:20:32 u010140856 阅读数 2463
  • 图像直方图统计

    掌握OpenCV核心模块,熟练使用相关API 理解各个API背后的相关算法原理,每个参数意义 有能力解决使用应用场景问题,大量工程代码经验分享 掌握图像处理与视频分析,图像分析与测量编码与开发技巧

    159人学习 贾志刚
    免费试看

QT进行数字图像处理-灰度直方图

 最近在学习数字图像处理方面的知识,为了加深学习的效果,使用Qt进行处理处理程序的编写,Qt提供了QImage类,该类中有图像处理的相关函数,简化了编程。由于能了有限,在此做记录,以便以后反思。首先进行了图像灰度直方图的编程,灰度直方图是一种
用来统计图像中像素灰度分布的工具。
void MainWindow::Imhist(QCustomPlot * plot, QImage *img)
{
    double yrange = 0;
    QVector<double> datax;
    QVector<double> datay;
    plot->clearGraphs();
    datay.resize(256);
    for(double i = 0; i < 256; i = i + 1)
       datax.append(i);
    QImage  grayimg = img->copy();
    unsigned char * data = grayimg.bits();
    //  对直方图进行数据处理
    int width = img->width();
    int hight = img->height();
    
    for(int i = 0; i <hight; i++)
    {
        for(int j = 0; j < width; j++)
        {
            datay.replace(data[i*hight + j],datay.at(data[i*hight + j])+1);
        }
    }
    
    QVector<double>::iterator it;
    for(it = datay.begin(); it != datay.end(); it++)
    {
        if(*it > yrange)
        yrange = *it;
    }

    plot->xAxis->setRange(0,256);  //x轴范围
    plot->yAxis->setRange(0,(int)yrange);  //y轴范围
    QCPBars *bars = new QCPBars(plot->xAxis, plot->yAxis);
    bars->setData(datax, datay);
    bars->setPen(QColor(0, 0, 0));
    bars->setWidth(0.05);
    plot->setVisible(true);
    plot->replot();
}




2015-12-01 21:47:40 GarfieldEr007 阅读数 9900
  • 图像直方图统计

    掌握OpenCV核心模块,熟练使用相关API 理解各个API背后的相关算法原理,每个参数意义 有能力解决使用应用场景问题,大量工程代码经验分享 掌握图像处理与视频分析,图像分析与测量编码与开发技巧

    159人学习 贾志刚
    免费试看

第三章 灰度直方图

目录

1.    灰度直方图

2.    直方图均衡化

3.    直方图规范化

4.    色彩直方图

作业


1.灰度直方图

灰度直方图(histogram)是灰度级的函数,它表示图象中具有每种灰度级的象素的个数,反映图象中每种灰度出现的频率。如下图所示,灰度直方图的横坐标是灰度级,纵坐标是该灰度级出现的频率,是图象的最基本的统计特征。

  

 从概率的观点来理解,灰度出现的频率可看作其出现的概率,这样直方图就对应于概率密度函数pdf(probability density function),而概率分布函数就是直方图的累积和,即概率密度函数的积分,如下图所示:

 
 

 

若直接从代表每种灰度的象素数目的直方图来观察,常用如下的表示:

 
 

 

灰度直方图的计算是很简单的,依据定义,若图象具有L(通常L=256,即8位灰度级)级灰度,则大小为MxN的灰度图象f(x,y)的灰度直方图hist[0…L-1]可用如下计算获得:

1.    初始化 hist[k]=0 ; k=0,…,L-1

2.    统计 hist[f(x,y)]++ ; xy =0,…,M-1, 0,…,N-1

3.    标准化 hist[f(x,y)]/=M*N

2.直方图均衡化

 直方图均衡化是通过灰度变换将一幅图象转换为另一幅具有均衡直方图,即在每个灰度级上都具有相同的象素点数的过程。

设灰度变换 s=f(r) 为斜率有限的非减连续可微函数,它将输入图象A(x,y)转换为输出图象B(x,y),输入图象的直方图为HA(r),输出图象的直方图为HB(s),则它们的关系可由如下过程导出:

 
 

 


 

例如,下图是直方图均衡化后的飞机图片及其直方图,可见其直方图与原图的直方图相比是很均衡的,但必须说明的是,离散情况下不可能作到绝对的一致。

  

 

3.直方图规范化

直方图规范化是指将一幅图象通过灰度变换后,使其具有特定的直方图形式,如使图象与某一标准图象具有相同的直方图,或使图象具有某一特定函数形式的直方图。

如下图所示,希望将图象A(x,y)变换为具有特定直方图H3(D)的图象C(x,y)。首先利用直方图均衡化将图象A(x,y)变换为具有平坦直方图的图象B(x,y),再利用第二个灰度变换将B(x,y)变换为C(x,y):

 

 

 

 

 

 

 

 

 

 

 

 
 

 

4.色彩直方图

 色彩直方图是高维直方图的特例,它统计色彩的出现频率,即色彩的概率分布信息。通常这需要一定的量化过程,将色彩分成若干互不重叠的种类。一般不直接在RGB色彩空间中统计,而是在将亮度分离出来后,对代表色彩部分的信息进行统计,如在HSI空间的HS子空间、YUV空间的UV子空间,以及其它反映人类视觉特点的彩色空间表示中进行。例如,下图是统计肤色分布情况的例子。

 

(图片来源:Lv Fengjun, Ai Haizhou, et.al., Face Detection Based on Skin Color and Template Matching, ICIG'2000, Aug.16-18, 2000.)

作业

1.编制直方图均衡化及直方图规范化程序(输入输出图象格式bmp)。


返回主目录 返回本章目录

清华大学计算机系 艾海舟

最近修改时间:2000年1月10日


http://media.cs.tsinghua.edu.cn/~ahz/digitalimageprocess/chapter03/chapt03_ahz.htm