精华内容
下载资源
问答
  • 【数字图像处理】灰度图像直方图的绘制与图像直方图均衡化增强图像对比度的matlab程序
    千次阅读
    2022-01-19 17:17:16

    程序内容描述如下:

    1.显示图像的直方图
    2.直方图均衡化用于增强图像的对比度,并显示直方图均衡化前后的图像与图像的直方图

    程序代码如下:

    %Part 1
    h=imread('cameraman.tif');
    subplot(1,2,1),imshow(h);
    subplot(1,2,2),imhist(h),
    grid on,
    ylabel('pixel count');
    %Part 2
    h=imread('cameraman.tif');
    subplot(1,6,1),imshow(h);
    g=histeq(h,40:60);
    j=imadjust(h,[0.3,0.7],[]);
    subplot(1,6,2),imshow(g);
    subplot(1,6,5),imhist(g);
    subplot(1,6,3),imshow(j);
    subplot(1,6,6),imhist(j);
    subplot(1,6,4),imhist(h),
    grid on,
    ylabel('pixel count');

    程序原理如下:

    part1,使用imread函数读取电脑磁盘中的图像cameraman.tif,使用函数imshow在图像窗口中显示图像,然后使用函数imhist获取图像的直方图并在图像窗口中显示。

    part2, 分别使用函数histeq和函数imadjust来均衡图像cameraman.tif的直方图,以增强图像对比度。我们使用函数imshow在图像窗口中显示原始图像、由函数histeq处理的图像和由函数imadjust处理的图像,然后使用函数imhist在图像窗口中显示三幅图像的直方图。

    程序运行结果如下:

    part1:

     图1:图像cameraman.tif及其直方图

    part2:

     图2:原始图像、增强对比度后的图像以及每幅图像的直方图

     看到这里的小伙伴别忘了点个赞再走哦!

    关注博主学习更多数字图像处理知识!

    更多相关内容
  • 灰度直方图,利用matlab实现图像直方图均衡化
  • """对一幅灰度图像进行直方图均衡化""" #计算图像的直方图 #在numpy中,也提供了一个计算直方图的函数histogram(),第一个返回的是直方图的统计量,第二个为每个bins的中间值 imhist,bins = histogram(im.flatten...
  • 今天小编就为大家分享一篇Python cv2 图像自适应灰度直方图均衡化处理方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 数字图像处理实验(1)--灰度图的直方图均衡化。编程实现灰度图像直方图均衡化处理。要求给出原始图像的直方图、均衡化图像及其直方图和直方图均衡化时所用的灰度级变换曲线图。
  • 图像灰度线性变换及直方图均衡化源代码图像灰度线性变换及直方图均衡化源代码图像灰度线性变换及直方图均衡化源代码图像灰度线性变换及直方图均衡化源代码图像灰度线性变换及直方图均衡化源代码图像灰度线性变换及...
  • 主要实现了彩色图像到灰度图像的转化,然后根据灰度图像进行直方图均衡化,用MATLAB 编写的,简单易懂。
  • 本文主要介绍了灰度直方图相关的处理,包括以下几个方面的内容:利用OpenCV计算图像灰度直方图,并绘制直方图曲线直方图均衡化的原理及实现直方图规定化(匹配)的原理及实现图像灰度直方图一幅图像由不同灰度值的...

    本文主要介绍了灰度直方图相关的处理,包括以下几个方面的内容:

    • 利用OpenCV计算图像的灰度直方图,并绘制直方图曲线
    • 直方图均衡化的原理及实现
    • 直方图规定化(匹配)的原理及实现

    图像的灰度直方图

    一幅图像由不同灰度值的像素组成,图像中灰度的分布情况是该图像的一个重要特征。图像的灰度直方图就描述了图像中灰度分布情况,能够很直观的展示出图像中各个灰度级所占的多少。

    图像的灰度直方图是灰度级的函数,描述的是图像中具有该灰度级的像素的个数:其中,横坐标是灰度级,纵坐标是该灰度级出现的频率。

    c0a810b4f22af6aad1f85575273399ae.png

    不过通常会将纵坐标归一化到[0,1]区间内,也就是将灰度级出现的频率(像素个数)除以图像中像素的总数。灰度直方图的计算公式如下:

    911e6b9a0f0d6845fb8717bdfbc90d98.png

    其中,rk是像素的灰度级,nk是具有灰度rk的像素的个数,MN是图像中总的像素个数。

    OpenCV灰度直方图的计算

    直方图的计算是很简单的,无非是遍历图像的像素,统计每个灰度级的个数。在OpenCV中封装了直方图的计算函数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 );

    该函数能够同时计算多个图像,多个通道,不同灰度范围的灰度直方图. 其参数如下

    • images,输入图像的数组,这些图像要有相同大大小,相同的深度(CV_8U CV_16U CV_32F).
    • nimages ,输入图像的个数
    • mask,可选的掩码,不使用时可设为空。要和输入图像具有相同的大小,在进行直方图计算的时候,只会统计该掩码不为0的对应像素
    • hist,输出的直方图
    • dims,直方图的维度
    • histSize,直方图每个维度的大小
    • ranges,直方图每个维度要统计的灰度级的范围
    • uniform,是否进行归一化,默认为true
    • accumulate,累积标志,默认值为false。

    为了计算的灵活性和通用性,OpenCV的灰度直方图提供了较多的参数,但对于只是简单的计算一幅灰度图的直方图的话,又显得较为累赘。这里对calcHist进行一次封装,能够方便的得到一幅灰度图直方图。

    class Histogram1D{private:    int histSize[1]; // 项的数量    float hranges[2]; // 统计像素的最大值和最小值    const float* ranges[1];    int channels[1]; // 仅计算一个通道public:    Histogram1D()    {        // 准备1D直方图的参数        histSize[0] = 256;        hranges[0] = 0.0f;        hranges[1] = 255.0f;        ranges[0] = hranges;        channels[0] = 0;    }    MatND getHistogram(const Mat &image)    {        MatND hist;        // 计算直方图        calcHist(&image ,// 要计算图像的            1,                // 只计算一幅图像的直方图            channels,        // 通道数量            Mat(),            // 不使用掩码            hist,            // 存放直方图            1,                // 1D直方图            histSize,        // 统计的灰度的个数            ranges);        // 灰度值的范围        return hist;    }    Mat getHistogramImage(const Mat &image)    {        MatND hist = getHistogram(image);        // 最大值,最小值        double maxVal = 0.0f;        double minVal = 0.0f;        minMaxLoc(hist, &minVal, &maxVal);        //显示直方图的图像        Mat histImg(histSize[0], histSize[0], CV_8U, Scalar(255));        // 设置最高点为nbins的90%        int hpt = static_cast(0.9 * histSize[0]);        //每个条目绘制一条垂直线        for (int h = 0; h < histSize[0]; h++)        {            float binVal = hist.at(h);            int intensity = static_cast(binVal * hpt / maxVal);            // 两点之间绘制一条直线            line(histImg, Point(h, histSize[0]), Point(h, histSize[0] - intensity), Scalar::all(0));        }        return histImg;    }};

    Histogram1D提供了两个方法:getHistogram返回统计直方图的数组,默认计算的灰度范围是[0,255];getHistogramImage将图像的直方图以线条的形式画出来,并返回包含直方图的图像。测试代码如下:

        Histogram1D hist;    Mat histImg;    histImg = hist.getHistogramImage(image);    imshow("Image", image);    imshow("Histogram", histImg);
    548857f68db74f6042f0b00554b1efec.png

    直方图均衡化 Histogram Equalization

    假如图像的灰度分布不均匀,其灰度分布集中在较窄的范围内,使图像的细节不够清晰,对比度较低。通常采用直方图均衡化及直方图规定化两种变换,使图像的灰度范围拉开或使灰度均匀分布,从而增大反差,使图像细节清晰,以达到增强的目的。

    直方图均衡化,对图像进行非线性拉伸,重新分配图像的灰度值,使一定范围内图像的灰度值大致相等。这样,原来直方图中间的峰值部分对比度得到增强,而两侧的谷底部分对比度降低,输出图像的直方图是一个较为平坦的直方图。

    均衡化算法

    直方图的均衡化实际也是一种灰度的变换过程,将当前的灰度分布通过一个变换函数,变换为范围更宽、灰度分布更均匀的图像。也就是将原图像的直方图修改为在整个灰度区间内大致均匀分布,因此扩大了图像的动态范围,增强图像的对比度。通常均衡化选择的变换函数是灰度的累积概率,直方图均衡化算法的步骤:

    • 计算原图像的灰度直方图
    8ff435a71c4b1954a882619b5643ed11.png

    ,其中n为像素总数,Nk为灰度级Sk的像素个数

    • 计算原始图像的累积直方图
    33083502190b73543080e9d49947ef14.png
    8b8ca39f2c4f1528e13f40880f7e5ba4.png

    其中Dj为目的图像的像素,

    692033985e0e7fb2f6b8f6638ec3eb0d.png

    是源图像灰度为i的累积分布,L是图像中最大灰度级(灰度图为255)

    其代码实现如下:

    • 在上面中封装了求灰度直方图的类,这里直接应用该方法得到图像的灰度直方图;
    • 将灰度直方图进行归一化,计算灰度的累积概率;
    • 创建灰度变化的查找表
    • 应用查找表,将原图像变换为灰度均衡的图像

    具体代码如下:

    void equalization_self(const Mat &src, Mat &dst){    Histogram1D hist1D;    MatND hist = hist1D.getHistogram(src);    hist /= (src.rows * src.cols); // 对得到的灰度直方图进行归一化    float cdf[256] = { 0 }; // 灰度的累积概率    Mat lut(1, 256, CV_8U); // 灰度变换的查找表    for (int i = 0; i < 256; i++)    {        // 计算灰度级的累积概率        if (i == 0)            cdf[i] = hist.at(i);        else            cdf[i] = cdf[i - 1] + hist.at(i);        lut.at(i) = static_cast(255 * cdf[i]); // 创建灰度的查找表    }    LUT(src, lut, dst); // 应用查找表,进行灰度变化,得到均衡化后的图像}

    上面代码只是加深下对均衡化算法流程的理解,实际在OpenCV中也提供了灰度均衡化的函数equalizeHist,该函数的使用很简单,只有两个参数:输入图像,输出图像。下图为,上述代码计算得到的均衡化结果和调用equalizeHist的结果对比

    a54546971e97abc795f10d2c760902b6.png

    最左边为原图像,中间为OpenCV封装函数的结果,右边为上面代码得到的结果。

    直方图规定化

    从上面可以看出,直方图的均衡化自动的确定了变换函数,可以很方便的得到变换后的图像,但是在有些应用中这种自动的增强并不是最好的方法。有时候,需要图像具有某一特定的直方图形状(也就是灰度分布),而不是均匀分布的直方图,这时候可以使用直方图规定化。

    直方图规定化,也叫做直方图匹配,用于将图像变换为某一特定的灰度分布,也就是其目的的灰度直方图是已知的。这其实和均衡化很类似,均衡化后的灰度直方图也是已知的,是一个均匀分布的直方图;而规定化后的直方图可以随意的指定,也就是在执行规定化操作时,首先要知道变换后的灰度直方图,这样才能确定变换函数。规定化操作能够有目的的增强某个灰度区间,相比于,均衡化操作,规定化多了一个输入,但是其变换后的结果也更灵活。

    • 将原始图像的灰度直方图进行均衡化,得到一个变换函数

    s = T(r)

    其中s是均衡化后的像素,r是原始像素

    • 对规定的直方图进行均衡化,得到一个变换函数

    v = G(z)

    其中v是均衡化后的像素,z是规定化的像素

    • 上面都是对同一图像的均衡化,其结果应该是相等的,
    6a187b72771ac05a7f7f11241de4e085.png

    详解规定化过程

    对图像进行直方图规定化操作,原始图像的直方图和以及规定化后的直方图是已知的。假设

    Pr(r)

    表示原始图像的灰度概率密度,Pz(z)表示规定化图像的灰度概率密度,(r和z分别是原始图像的灰度级,规定化后图像的灰度级)。

    • 对原始图像进行均衡化操作,则有
    7e4f86e8db8efd6fb6b1a67308ddf678.png
    • 对规定化的直方图进行均衡化操作,则
    9e2150104f04574354a2ed08ffcb9ab4.png
    • 由于是对同一图像的均衡化操作,所以有
    0803d41addfb34a44d39f32365394c50.png
    • 规定化操作的目的就是找到原始图像的像素sk sk 到规定化后图像像素的zk之间的一个映射。有了上一步的等式后,可以得到sk=G(zk),因此要想找到sk想对应的zk只需要在z进行迭代,找到使式子G(zm)−sk的绝对值最小即可。
    • 上述描述只是理论的推导过程,在实际的计算过程中,不需要做两次的均衡化操作,具体的推导过程如下:
    0d7fb633db4f829f5a080bda9de718d0.png

    上面公式表示,假如$s_k$ 规定化后的对应灰度是$z_m$的话,需要满足的条件是$s_k$的累积概率和$z_m$的累积概率是最接近的。 下面是一个具体计算的例子:

    1439dbe31f81c2359e6269bbe6de1e6d.png

    首先得到原直方图的各个灰度级的累积概率$V_s$以及规定化后直方图的各个灰度级的累积概率$V_z$,那么确定$s_k$到$z_m$之间映射关系的条件就是:$$mid V_s - V_z mid$$的值最小。 以$k = 2$为例,其原始直方图的累积概率是:0.65,在规定化后的直方图的累积概率中和0.65最接近(相等)的是灰度值为5的累积概率密度,则可以得到原始图像中的灰度级2,在规定化后的图像中的灰度级是5

    直方图规定化的实现

    直方图规定化的实现可以分为一下三步:

    • 计算原图像的累积直方图
    • 计算规定直方图的累积直方图
    • 计算两累积直方图的差值的绝对值
    • 根据累积直方图差值建立灰度级的映射

    具体代码实现如下:

    void hist_specify(const Mat &src, const Mat &dst,Mat &result){    Histogram1D hist1D;    MatND src_hist = hist1D.getHistogram(src);    MatND dst_hist = hist1D.getHistogram(dst);    float src_cdf[256] = { 0 };    float dst_cdf[256] = { 0 };    // 源图像和目标图像的大小不一样,要将得到的直方图进行归一化处理    src_hist /= (src.rows * src.cols);    dst_hist /= (dst.rows * dst.cols);    // 计算原始直方图和规定直方图的累积概率    for (int i = 0; i < 256; i++)    {        if (i == 0)        {            src_cdf[i] = src_hist.at(i);            dst_cdf[i] = dst_hist.at(i);        }        else        {            src_cdf[i] = src_cdf[i - 1] + src_hist.at(i);            dst_cdf[i] = dst_cdf[i - 1] + dst_hist.at(i);        }    }    // 累积概率的差值    float diff_cdf[256][256];    for (int i = 0; i < 256; i++)        for (int j = 0; j < 256; j++)            diff_cdf[i][j] = fabs(src_cdf[i] - dst_cdf[j]);    // 构建灰度级映射表    Mat lut(1, 256, CV_8U);    for (int i = 0; i < 256; i++)    {        // 查找源灰度级为i的映射灰度        // 和i的累积概率差值最小的规定化灰度        float min = diff_cdf[i][0];        int index = 0;        for (int j = 1; j < 256; j++)        {            if (min > diff_cdf[i][j])            {                min = diff_cdf[i][j];                index = j;            }        }        lut.at(i) = static_cast(index);    }    // 应用查找表,做直方图规定化    LUT(src, lut, result);}

    上面函数的第二个参数的直方图就是规定化的直方图。代码比较简单,这里就不一一解释了。其结果如下:

    02bc18b43ee5aad14116c41d0ab92daa.png

    左边是原图像,右边是规定化的图像,也就是上面函数的第一个和第二个输入参数。原图像规定化的结果如下:

    62b65c6a01b09f71e87904b72026f1fd.png

    原图像规定化后的直方图和规定化的图像的直方图的形状比较类似, 并且原图像规定化后整幅图像的特征和规定化的图像也比较类似,例如:原图像床上的被子,明显带有规定化图像中水的波纹特征。

    直方图规定化过程中,在做灰度映射的时候,有两种常用的方法:

    • 单映射 Single Mapping Law,SML,这种方法也是上面使用的方法,根据累积直方图的差值,从原图像中找到其在规定化图像中的映射。
    • 组映射 Group Mapping Law,GML 这种方法较上述方法复杂不少,但是处理效果较好。

    对于GML的映射方法,一直没有很好的理解,但是根据其算法描述实现了该方法,代码这里先不放出,其处理结果如下:

    1fe574a02e8fd93514ed605a335ce5a0.png

    其结果较SML来说更为亮一些,床上的波浪特征也更为明显,但是其直方图形状,和规定化的直方图对比,第一个峰不是很明显。

    总结

    • 图像的灰度直方图能够很直观的展示图像中灰度级的整体分布情况,对图像的后续处理有很好的指导作用。
    • 直方图的均衡化的是将一幅图像的直方图变平,使各个灰度级的趋于均匀分布,这样能够很好的增强图像对比度。直方图均衡化是一种自动化的变换,仅需要输入图像,就能够确定图像的变换函数。但是直方图的均衡化操作也有一定的确定,在均衡化的过程中对图像中的数据不加选择,这样有可能会增强图像的背景;变换后图像的灰度级减少,有可能造成某些细节的消失;会压缩图像直方图中的高峰,造成处理后图像对比度的不自然等。
    • 直方图规定化,也称为直方图匹配,经过规定化处理将原图像的直方图变换为特定形状的直方图(上面中的示例,就是将图像的直方图变换为另一幅图像的直方图)。它可以按照预先设定的它可以按照预先设定的某个形状来调整图像的直方图,运用均衡化原理的基础上,通过建立原始图像和期望图像
    展开全文
  • 灰度图像直方图均衡化变换函数算法.doc
  • 1、读取一张图片,将其转换为HSV空间\对RGB三个通道分别画出其三维图(提示:polt_sufface函数)2、读取彩色图像home_color;画出灰度图像home_gray的灰度直方图,并拼接原...5、编程实现直方图均衡化,给出测试效果
  • 灰度图像直方图均衡化公式及实现

    万次阅读 2018-01-28 17:35:08
    灰度图像直方图均衡化公式及实现

    图像的直方图:直方图是图像中像素强度分布的图形表达方式。它统计了每一个强度值所具有的像素个数

    直方图均衡化:是通过拉伸像素强度分布范围来增强图像对比度的一种方法。是图像处理领域中利用图像直方图对对比度进行调整的方法。

    均衡化指的是把一个分布(给定的直方图)映射到另一个分布(一个更宽更统一的强度值分布),所以强度值分布会在整个范围内展开。映射函数应该是一个累积分布函数(cumulative distribution function(cdf))。

    直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。

    这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。

    灰度直方图均衡化算法实现步骤:

    (1)、统计原始图像各灰度级的像素数目ni,0≤i<L, L是图像中所有的灰度数(通常为256);

    (2)、图像中灰度为i的像素的出现概率是:px(i)=p(x=i)=ni/n,n是图像中所有的像素数,px(i)实际上是像素值为i的图像的直方图,归一化到[0, 1];

    (3)、px的累积分布函数,是图像的累计归一化直方图:


    (4)、直方图均衡化计算公式, cdfmin为累积分布函数最小值,M和N分别代表了图像的长宽像素个数,而L则是灰度级数(如图像为8位深度,则灰度级别共有2^8=256级数,这也是最常见的灰度级数),v为原始图像中为v的像素值:


    彩色图像直方图均衡化:上面描述了灰度图像上使用直方图均衡化的方法,但是通过将这种方法分别用于图像RGB颜色值的红色、绿色和蓝色分量,从而也可以对彩色图像进行处理。实际上,对彩色分量rgb分别做均衡化,会产生奇异的点,图像不和谐。一般采用的是用yuv空间进行亮度的均衡即可。

    以上内容主要参考:维基百科

    以下是分别采用C++和OpenCV实现的code,从执行结果可知,C++和OpenCV的结果完全一致:

    histogram_equalization.cpp:

    #include "funset.hpp"
    #include <chrono>
    #include <vector>
    #include <algorithm>
    #include "common.hpp"
    
    int histogram_equalization_cpu(const unsigned char* src, int width, int height, unsigned char* dst, float* elapsed_time)
    {
    	//TIME_START_CPU
    
    	const int hist_sz{ 256 };
    	std::vector<int> hist(hist_sz, 0), lut(hist_sz, 0);
    	for (int y = 0; y < height; ++y) {
    		for (int x = 0; x < width; ++x) {
    			++hist[src[y * width + x]];
    		}
    	}
    
    	int i{ 0 };
    	while (!hist[i]) ++i;
    
    	int total{ width * height };
    	if (hist[i] == total) {
    		unsigned char* p = dst;
    		std::for_each(p, p + total, [i](unsigned char& value) { value = i; });
    		return 0;
    	}
    
    	float scale = (hist_sz - 1.f) / (total - hist[i]);
    	int sum = 0;
    
    	for (lut[i++] = 0; i < hist_sz; ++i) {
    		sum += hist[i];
    		lut[i] = static_cast<unsigned char>(sum * scale + 0.5f);
    	}
    
    	for (int y = 0; y < height; ++y) {
    		for (int x = 0; x < width; ++x) {
    			dst[y * width + x] = static_cast<unsigned char>(lut[src[y * width + x]]);
    		}
    	}
    
    	//TIME_END_CPU
    
    	return 0;
    }
    main.cpp:

    #include "funset.hpp"
    #include <random>
    #include <iostream>
    #include <vector>
    #include <memory>
    #include <string>
    #include <algorithm>
    #include "common.hpp"
    
    int test_image_process_histogram_equalization()
    {
    	const std::string image_name{ "E:/GitCode/CUDA_Test/test_data/images/lena.png" };
    	cv::Mat mat = cv::imread(image_name, 0);
    	CHECK(mat.data);
    
    	const int width{ mat.cols/*1513*/ }, height{ mat.rows/*1473*/ };
    	cv::resize(mat, mat, cv::Size(width, height));
    
    	std::unique_ptr<unsigned char[]> data1(new unsigned char[width * height]), data2(new unsigned char[width * height]);
    	float elapsed_time1{ 0.f }, elapsed_time2{ 0.f }; // milliseconds
    
    	CHECK(histogram_equalization_cpu(mat.data, width, height, data1.get(), &elapsed_time1) == 0);
    	//CHECK(histogram_equalization_gpu(mat.data, width, height, data2.get(), &elapsed_time2) == 0);
    
    	//fprintf(stdout, "image histogram equalization: cpu run time: %f ms, gpu run time: %f ms\n", elapsed_time1, elapsed_time2);
    
    	cv::Mat dst;
    	cv::equalizeHist(mat, dst);
    	cv::imwrite("E:/GitCode/CUDA_Test/test_data/images/histogram_equalization.png", dst);
    
    	CHECK(compare_result(data1.get(), dst.data, width*height) == 0);
    	//CHECK(compare_result(data1.get(), data2.get(), width*height) == 0);
    
    	save_image(mat, dst, width, height/2, "E:/GitCode/CUDA_Test/test_data/images/histogram_equalization_result.png");
    
    	return 0;
    }
    执行结果:




    展开全文
  • 图像灰度直方图的均衡化和规定化 matlab灰度直方图均衡化均衡化步骤:代码实现:结果对比:规定化:定义:作用:做法:主要映射方法:结果对比: 灰度直方图 灰度直方图:反映了该图像中不同灰度级出现的统计情况。 ...

    灰度直方图

    灰度直方图:反映了该图像中不同灰度级出现的统计情况。
    举例如下:在这里插入图片描述

    均衡化

    均衡化:就是把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布。
    将图像的灰度直方图表示为一个一维的离散函数:
    在这里插入图片描述

    因此直方图的每一列就是nk的值。
    进一步得到归一化的直方图,表示为灰度值出现的频率:
    在这里插入图片描述

    因此均衡化的操作就是对于每一个原图像的灰度值,确立一个映射函数,使其对应一个新的灰度值,而新图像的所有新灰度值应该均匀分布,换言之,映射函数需要满足以下条件:

    1. 在 0 ≤ r ≤ 1 内,T® 为单调递增函数;(此条件保证了均衡化后图像的灰度级从黑到白的次序不变)
    2. 在 0 ≤ r ≤ 1 内有 0 ≤ T® ≤ 1。(此条件保证了均衡化后图像的像素灰度值在允许的范围内)
      新灰度值均匀分布在0,1之间,即均衡化。

    均衡化步骤:

    第一步,计算原始图像的灰度直方图 。
    第二步,计算原始图像的像素总个数。
    第三步,计算原始图像的灰度分布频率。
    第四步,计算原始图像的灰度累积分布频率。
    第五步,将归一化的 乘以 再四舍五入,以使得均衡化后图像的灰度级与归一化前的原始图像一致。
    第六步,根据以上映射关系,参照原始图像中的像素,可以写出直方图均衡化之后的图像。

    代码实现:

    close all; 
    clear; 
    clc; 
     
    % 首先读入灰度图像,并提取图像的高度和宽度
    image = imread('1.jpg'); 
    [m,n,z]=size(image);
    if z>1
        image = rgb2gray(image);
    end
    [height, width] = size(image); 
     
    % 然后统计每个灰度的像素值的累计数目
    NumPixel = zeros(1,256);  % 建立一个256列的行向量,以统计各灰度级的像素个数
    for i = 1 : height
       for j = 1 : width
           k = image(i,j);  % k是像素点(i,j)的灰度值
           % 因为NumPixel数组的下标是从1开始的,但是图像像素的取值范围是0~255
           % 所以用NumPixel(k+1)
           NumPixel(k+1) = NumPixel(k+1) + 1;  % 对应灰度值像素点数量加1 
       end
    end
    
     
    % 接下来,将频数值算为频率
    ProbPixel = zeros(1,256); % 统计各灰度级出现的频率
    for i = 1 : 256
        ProbPixel(i) = NumPixel(i) / (height * width);
    end
    
     
    % 再用函数cumsum()来计算累积分布函数(CDF),并将频率(取值范围是0~1)映射到0~255的无符号整数
    CumPixel = cumsum(ProbPixel);  % 这里的数组CumPixel大小也是1×256
    CumPixel = uint8((256-1) .* CumPixel + 0.5); 
    
     
    % 在下列用作直方图均衡化实现的赋值语句右端,image(i,j)被用来作为CumPixel的索引
    % 例如,image(i,j)=120,则从CumPixel中取出第120个值作为image(i,j)的新像素值
    outImage = uint8(zeros(height, width));  % 预分配数组
    for i = 1 : height
       for j = 1 : width
          outImage(i,j) = CumPixel(image(i,j)+1);
       end
    end
    srceq=histeq(image);
     
    subplot(3,3, 1);
        imshow(image);
        title('(a)');
    subplot(3,3, [2 3])
        imhist(image);
        title('(b)');
    subplot(3,3, 4);
        imshow(outImage);
        title('(c)');
    subplot(3,3, [5 6]);
        imhist(outImage);
        title('(d)');
        subplot(3,3, 7);
        imshow(srceq);
        title('(c)');
    subplot(3,3, [8 9]);
        imhist(srceq);
        title('(d)');
    
    

    结果对比:

    在这里插入图片描述

    结果将自行处理的图像与标准库均衡化代码处理的图像进行输出对比,图像显示基本一致,而直方图显示略有不同。

    规定化:

    规定化是在均衡化的基础上操作的,和均衡化的最大不同就是规定化的结果是已知的。

    定义:

    在运用均衡化原理基础上,通过建立原始图像和期望图像(待匹配直方图图像)之间的关系,使原始图像的直方图匹配特定的形状,从而弥补直方图均衡化不具备交互作用的特性。

    作用:

    1.可以自动确定灰度变换函数,从而获得具有均匀直方图的输出图像。
    2.增强动态范围偏小的图像对比度。

    做法:

    要利用均衡化图像作为中间件,实现原图像到匹配图像的跨越。
    在这里插入图片描述

    通俗说就是:A通过s1映射为A1,C通过s2映射为C1。由上图知A1=C1,所以可以由A映射到C。实际上A1里的元素不一定都存在于C1中,当发现元素b属于A1但不属于C1时,找C1中与b最接近的元素进行匹配。

    主要映射方法:

    在这里插入图片描述

    结果对比:

    在这里插入图片描述

    展开全文
  • 直方图均衡化C++代码

    2017-06-01 21:35:24
    直方图均衡化C++代码
  • 灰度图像直方图均衡化,主要步骤: 1. 计算每一个灰度级的概率 2. 计算每一个灰度级的累计概率 3. 计算映射表 4. 将图像像素值通过映射表进行映射 对于直方图均衡化原理,参考博文:直方图均衡化原理 代码实现如下...
  • matlab 灰度图像直方图均衡化
  • 1. 彩色图像转换为灰度图像; 2. 根据灰度图像的灰度值分布情况,绘制直方图; 3. 直方图均衡化; 4. 根据灰度图片直方图进行图像分割; 包含文档、Java和Matlab代码、结果图等
  • 图像灰度直方图 以及 直方图均衡化 1 一张图片可以看作 由许许多多不同灰度值的像素组成 2. 灰度图直方图 表示 在不同灰度下的像素数量 3. 通常为 UINT8 0~255 表示 三通道RGB 图像 特定情况下,需要转化 RGB TO ...
  • matlab灰度直方图均衡化代码clear all%一,图像的预处理,读入彩色图像将其灰度化PS=imread('1.jpg'); %读入JPG彩色图像文件imshow(PS) %显示出来title('输入的彩色JPG图像')imwrite(rgb2gray(PS),'PicSampleGray....
  • 直方图均衡化的作用是图像增强。 原理 参考这篇文章 实验步骤 实现代码 function [J] = imhisteq(I) [M,N,C]=size(I); %获得输入图像尺寸M、N、C(size函数) I0 = double(I);%矩阵F中的数据由uint8类型转换为...
  • 图像处理中,直方图是非常重要,也是非常有用的一个处理要素。这篇文章主要介绍了python数字图像处理实现直方图均衡化,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
  •   图像直方图(Image Histogram)是用以表示数字图像中亮度分布的直方图,标绘了图像中每个亮度值的像素个数。这种直方图中,横坐标的左侧为较暗的区域,而右侧为较亮的区域。因此一张较暗图片的直方图中的数据多...
  • 基于Matlab的图像直方图均衡化灰度变换内容练习。
  • 规定化直方图 规定灰度为[zeros(1,49),0.1,zeros(1,49),0.2,zeros(1,49),0.3,zeros(1,49),0.1,zeros(1,49),0.2,zeros(1,49),0.1] 均衡化直方图
  • 数字图像处理,直方图均衡,直方图匹配,作业
  • opencv-python 实现灰度图像和彩色图像直方图全局均衡化和自适应均衡化 内容来自博客~ 首先进行简单的灰度图像的全局均衡化和自适应均衡化 import cv2 as cv import numpy as np # 读取本地图像 img=cv.imread('C:...
  • 考查结构体、文件读写、简单的图像处理算法 从bmp文件(如灰度图像woman.bmp、彩色图像lenna.bmp)读入图像数据 对图像数据进行均衡处理 ...必做功能1:灰度图像直方图均衡 必做功能2:彩色图像的直方图均衡

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 11,152
精华内容 4,460
关键字:

灰度图像直方图均衡化