2019-01-22 20:56:42 xiaoheizi_du 阅读数 411

版权声明:本文为博主原创文章,未经博主允许不得转载。


数字图像处理02:直方图均衡化imhist函数的python实现

1、直方图均衡

直方图均衡就是将灰度比较集中一定范围的图像通过灰度映射/变换,使其灰度值平均分布在灰度级的范围内,以得到图像的更多细节,从而达到对比度增强的效果。

2、直方图均衡化的原理公式

1. 连续情况
在这里插入图片描述
其中Pr( r )Ps(s)分别是原始图像灰度级r和变换后图像的灰度级s的概率密度函数PDFL-1为图像的最大灰度级。上一个公式表示的是rPDFPr( r )和sPDFPs(s)的关系。给定一个输入,则Pr( r )已知,就可以求出s,继而求出Ps(s)。rs的映射关系即为均衡化关系。由Pr( r )Ps(s)可以得出输入图像的直方图和变换后的输出图像的直方图。
在这里插入图片描述
在这里插入图片描述
再经过以上两个公式的推导,可以得出结论Ps(s)=1/(L-1),可知该变换s=t( r )就是取均值。
2. 离散情况
对于图像来说,其实应该是离散情况。
在这里插入图片描述
在这里插入图片描述
其中MN为图像的像素总个数。以上两个公式是“1”中公式的离散情况,在实际对图像进行操作中也应该是离散情况下进行操作计算。

3、离散情况举例

注:该例子对应于冈萨雷斯.《数字图像处理(第三版)》中文翻译版,第76面例3.5。
在这里插入图片描述
上图中的数据经过‘2’中的公式计算得到经过变换的r对应的s值分别为:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
S0~S7经过四舍五入取整:
在这里插入图片描述
可以看原始图像数据像素集中在r0~r3 即灰度0~3,经过均衡化变换后,将0变换为11变换为32变换为53、4变换为65、6、7变换为7,这样就将灰度分散开。所谓均衡变换也就是灰度级的映射变换,即将灰度级密度大值的映射成其它原来灰度级密度小的值,以达到一种均衡化/平均的效果。从rs的映射将集中的r分散到其他灰度,即将灰度值r变为其他灰度值,达到均衡化。

4、直方图均衡化计算步骤

在这里插入图片描述
其中第四步计算累积直方图是为了下一步(第五步)计算变换后对应的灰度值,而第五步中先加0.5再作INT(取整)操作即是四舍五入取整操作(此操作对于编程实现非常有用)。
对例3.5的具体步骤如下:
在这里插入图片描述
注:此上两张图来源于许录平.科学出版社. 《数字图像处理》. 配套教学PPT。

5、Matlab中直方图均衡化的imhist函数

h=imhist(f, b),其中f为输入图像,h为直方图,b是用来形成直方图的“统计堆栈”的数目。“统计堆栈”仅仅是灰度的一小部分。例如我们处理一幅uint8类的图像且设b=2,然后灰度范围被分成两部分:0至127和128至255。所得的直方图将有两个值:h(1)等于图像在[0,127]间隔内的像素数,h(2)等于图像在[128,255]间隔内的像素数。通过下列表达式就可以得到归一化的直方图:p=imhist(f, b)/numel(f)numel(f)函数可以给出数组f中元素的个数(即图像中的像素数)。

6、python代码实现

1. 显示图像标题所需的字体

from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']

2. 需要导入的库

import numpy as np
import matplotlib.pyplot as plt
from scipy import misc

3.画条形图/直方图或者可视化所需要的包和函数创建。
由于用matplotlib自带的绘制条形图/直方图的包imhist绘图时出现了问题,所以就选择了之前用过的数据可视化的绘图包pyechartspyecharts函数包的是一个可以根据数据绘制条形图/折线图/饼状图的python绘图包,具体用法请见主页:pyecharts 文档

# 画条形图/直方图 或者可视化。导入pyecharts函数包
import os
from pyecharts import Bar,Pie,Line
# 创建直方图/条形图绘制函数
def get_charts(x, y, label, type):
    
    if type==1:
        c = Pie('饼状图')
    elif type==2:
        c = Bar('条形图')
    elif type==3:
        c = Line('折线图')
    c.add(label, x, y, is_more_utils=True)
    c.show_config()
    c.render()
    os.system(r"render.html")

其中xy分别是要绘制图形的x轴和y轴的数据,label为图形的标注/标签,type1、2、3分别表示 ‘饼状图’‘条形图’‘折线图’,操作实现非常简单,而且绘制出来的图形非常好看。

4.imhist函数实现

# imhist函数构建,img为原始图像,L为其灰度级
def imhist(img, L):
    
    f = misc.imread(img)
    plt.figure(1)
    plt.imshow(f, cmap='gray')
    plt.axis('off')
    plt.title('原始图像')
    plt.show()
    
    
    w, h = f.shape
    f1 = np.zeros([w, h])
    pallel = dict((i,0) for i in range(L))
    # 计算原始图像灰度级像素个数ni
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            if i in pallel:
                pallel[i] = pallel[i] + 1
            else:
                pallel[i] = 1
    
    key = [i for i in range(L)]     # key为灰度级,即0~255
    value1 = [pallel[i] for i in range(L)]      # value1为各灰度级的像素个数ni
    n = w * h
    
    #计算原始图像的直方图,value2为原始图像的直方图P(i) = ni/n = ni/(w*h)
    value2 = [value1[i]/n for i in range(L)]        
    
    # 计算累积直方图,value3为累积直方图Pj
    value3 = [0 for i in range(L)]             
    value3[0] = value2[0]
    for j in range(1, L):
        value3[j] = value3[j-1] + value2[j]
    
    # 计算灰度值变换,value4为由r变换为s后的灰度值
    value4 = [0 for i in range(L)]          
    for j in range(L):
        value4[j] = int((L-1) * value3[j] + 0.5)
    
    # 计算变换后各灰度级的像素个数nj,value5即为nj
    value5 = [0 for j in range(L)]
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            t = value4[i]
            f1[x, y] = t
            for k in range(L):
                if (t == k):
                    value5[k] = value5[k] + 1
#            j = f1[x, y]
#            if t in value5:
#                value5[t] = value5[t] + 1
#            else:
#                value5[t] = 1

    
    # 计算变换后图像的直方图,value6即为P(j)
    value6 = [value5[i]/n for i in range(L)]
    
    
    # 均衡化后的图像
    scipy.misc.imsave('huafen2_2.png', f1)
    plt.figure(2)
    plt.imshow(f1, cmap='gray') 
    plt.axis('off')
    plt.title('变换图像')
    plt.show()
    
    return f1, f, pallel, key, value1, value2, value3, value4, value5, value6

(1) 其中,img为输入图像,L为最大灰度级,如256。

(2)

    f = misc.imread(img)
    plt.figure(1)
    plt.imshow(f, cmap='gray')
    plt.axis('off')
    plt.title('原始图像')
    plt.show()

这段代码用来读入原始图像。

(3)

    pallel = dict((i,0) for i in range(L))
    # 计算原始图像灰度级像素个数ni
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            if i in pallel:
                pallel[i] = pallel[i] + 1
            else:
                pallel[i] = 1
    
    key = [i for i in range(L)]     # key为灰度级,即0~255
    value1 = [pallel[i] for i in range(L)]      # value1为各灰度级的像素个数ni
    n = w * h

pallel表示由原图像的灰度值和该灰度值的个数作为键值对的字典,灰度值为键,个数为值。首先创建一个长度为L的空字典,然后遍历图像,通过两个判断语句ifelse将图像灰度值的个数添加到字典pallel中,如果灰度值ipallel中,则pallel[i]对应的i这个灰度值的个数加一,否则 灰度值i的个数等于一,依次遍历整个图像矩阵。最后将灰度级0~255存到列表key中,将各灰度级的个数存到value1中。

(4) 然后按照 ‘4、’ 中的8个步骤依次计算剩余的变量/数据列表。

#计算原始图像的直方图,value2为原始图像的直方图P(i) = ni/n = ni/(w*h)
    value2 = [value1[i]/n for i in range(L)]        
    
    # 计算累积直方图,value3为累积直方图Pj
    value3 = [0 for i in range(L)]             
    value3[0] = value2[0]
    for j in range(1, L):
        value3[j] = value3[j-1] + value2[j]
    
    # 计算灰度值变换,value4为由r变换为s后的灰度值
    value4 = [0 for i in range(L)]          
    for j in range(L):
        value4[j] = int((L-1) * value3[j] + 0.5)
    
    # 计算变换后各灰度级的像素个数nj,value5即为nj
    value5 = [0 for j in range(L)]
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            t = value4[i]
            f1[x, y] = t
            for k in range(L):
                if (t == k):
                    value5[k] = value5[k] + 1
#            j = f1[x, y]
#            if t in value5:
#                value5[t] = value5[t] + 1
#            else:
#                value5[t] = 1

    
    # 计算变换后图像的直方图,value6即为P(j)
    value6 = [value5[i]/n for i in range(L)]

(5) 保存并显示均衡化变换后代图像,并返回各数据列表

    # 均衡化后的图像
    scipy.misc.imsave('huafen2_2.png', f1)
    plt.figure(2)
    plt.imshow(f1, cmap='gray') 
    plt.axis('off')
    plt.title('变换图像')
    plt.show()
        
    return f1, f, pallel, key, value1, value2, value3, value4, value5, value6

5. 测试imhist函数,并绘制条形图/直方图

# imhist函数测试        
f1, f,pallel, key, value1, value2, value3, value4, value5, value6 = imhist('huafen2.tif', 256)

# 绘制原始图像灰度级像素个数的条形图
label1 = "灰度级:像素个数"
type = 2     # type = 2表示条形图
get_charts(key, value1, label1, type)

# 绘制原始图像灰度级概率密度的条形图
label2 = "灰度级:概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value2, label2, type)

# 绘制原始图像的累积直方图
label3 = "灰度级:累积概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value3, label3, type)

# 绘制映射变换关系的条形图
label3 = "灰度级:灰度级"
type = 2     # type = 2表示条形图
get_charts(key, value4, label3, type)

# 绘制变换后图像灰度级像素个数的条形图
label3 = "灰度级:像素个数"
type = 2     # type = 2表示条形图
get_charts(key, value5, label3, type)

# 绘制变换后图像灰度级概率密度的条形图
label3 = "灰度级:概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value6, label3, type)

输入图像f冈萨雷斯.《数字图像处理(第三版)》中文翻译版 第三章的例图 “huafen”:
在这里插入图片描述
均衡化变换后的图像f1为:
在这里插入图片描述
经过均衡化变换后,原始的暗色图象个变亮了,可以得到图像的更多细节。
(1) value1的条形图(原始图像各灰度值的个数统计图)如下:
在这里插入图片描述
在该条形图中可以看出原始图像的各像素值的个数,以及其主要分布在较低的灰度级,所以原始图像看上去比较暗。
(2) value2的直方图(原始图像各灰度级的概率密度图)如下:
在这里插入图片描述
(3) value3的条形图(原始图像各灰度级的原始图像的累积直方图)如下:
在这里插入图片描述
(4) value4的条形图(原始图像各灰度级的映射关系图)如下:
在这里插入图片描述
从这幅图可以看到原始图像灰度值到变换后图像灰度值的映射关系。
(5) value5的条形图(变换后图像各灰度值的个数统计图)如下:
在这里插入图片描述
从这幅图可以看出,均衡化变换后图像的灰度值均匀的分布在灰度空间,达到了均衡化的效果。

(6) value6的直方图(变换后图像各灰度级的概率密度图)如下:
在这里插入图片描述

6. 整体代码

# -*- coding: utf-8 -*-
"""
Created on Sun Jan 20 09:20:58 2019

@author: ChengGD
"""

# 图像显示窗口标题需要的中文字体
from pylab import mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']


#from PIL import Image
import numpy as np
import matplotlib.pyplot as plt
from scipy import misc
import scipy 
#import cv2


# 画条形图/直方图 或者可视化。导入pyecharts函数包
import os
from pyecharts import Bar,Pie,Line
# 创建直方图/条形图绘制函数
def get_charts(x, y, label, type):
    
    if type==1:
        c = Pie('饼状图')
    elif type==2:
        c = Bar('条形图')
    elif type==3:
        c = Line('折线图')
    c.add(label, x, y, is_more_utils=True)
    c.show_config()
    c.render()
    os.system(r"render.html")


# imhist函数构建,img为原始图像,L为其灰度级
def imhist(img, L):
    
    f = misc.imread(img)
    plt.figure(1)
    plt.imshow(f, cmap='gray')
    plt.axis('off')
    plt.title('原始图像')
    plt.show()
    
    
    w, h = f.shape
    f1 = np.zeros([w, h])
    pallel = dict((i,0) for i in range(L))
    # 计算原始图像灰度级像素个数ni
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            if i in pallel:
                pallel[i] = pallel[i] + 1
            else:
                pallel[i] = 1
    
    key = [i for i in range(L)]     # key为灰度级,即0~255
    value1 = [pallel[i] for i in range(L)]      # value1为各灰度级的像素个数ni
    n = w * h
    
    #计算原始图像的直方图,value2为原始图像的直方图P(i) = ni/n = ni/(w*h)
    value2 = [value1[i]/n for i in range(L)]        
    
    # 计算累积直方图,value3为累积直方图Pj
    value3 = [0 for i in range(L)]             
    value3[0] = value2[0]
    for j in range(1, L):
        value3[j] = value3[j-1] + value2[j]
    
    # 计算灰度值变换,value4为由r变换为s后的灰度值
    value4 = [0 for i in range(L)]          
    for j in range(L):
        value4[j] = int((L-1) * value3[j] + 0.5)
    
    # 计算变换后各灰度级的像素个数nj,value5即为nj
    value5 = [0 for j in range(L)]
    for x in range(0,w):
        for y in range(0,h):
            i = f[x, y]
            t = value4[i]
            f1[x, y] = t
            for k in range(L):
                if (t == k):
                    value5[k] = value5[k] + 1
#            j = f1[x, y]
#            if t in value5:
#                value5[t] = value5[t] + 1
#            else:
#                value5[t] = 1

    
    # 计算变换后图像的直方图,value6即为P(j)
    value6 = [value5[i]/n for i in range(L)]
    
    
    # 均衡化后的图像
    scipy.misc.imsave('huafen2_2.png', f1)
    plt.figure(2)
    plt.imshow(f1, cmap='gray') 
    plt.axis('off')
    plt.title('变换图像')
    plt.show()
    
    return f1, f, pallel, key, value1, value2, value3, value4, value5, value6
    
# imhist函数测试        
 f1, f, pallel, key, value1, value2, value3, value4, value5, value6 = imhist('huafen2.tif', 256)

# 绘制原始图像灰度级像素个数的条形图
label1 = "灰度级:像素个数"
type = 2     # type = 2表示条形图
get_charts(key, value1, label1, type)

# 绘制原始图像灰度级概率密度的条形图
label2 = "灰度级:概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value2, label2, type)

# 绘制原始图像的累积直方图
label3 = "灰度级:累积概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value3, label3, type)

# 绘制映射变换关系的条形图
label3 = "灰度级:灰度级"
type = 2     # type = 2表示条形图
get_charts(key, value4, label3, type)

# 绘制变换后图像灰度级像素个数的条形图
label3 = "灰度级:像素个数"
type = 2     # type = 2表示条形图
get_charts(key, value5, label3, type)

# 绘制变换后图像灰度级概率密度的条形图
label3 = "灰度级:概率密度"
type = 2     # type = 2表示条形图
get_charts(key, value6, label3, type)
2019-10-04 21:54:35 effort_study 阅读数 27

直方图相当于一个图像中所有像素个数的统计表,x轴为图像的灰度级,从0到L-1,y轴是对应灰度级的个数。

绘制直方图

核心函数是imhist函数,语法形式h=imhist(f,b),f表示输入的图像,b表示统计灰度级的个数,省略时默认为256.通过p=imhist(f,b)/numel(f)可以获得归一化的直方图,numel函数可以给出数组f中元素的个数。
例:使用imhist函数和stem函数绘制杆状直方图

clf;
clear;
f=imread('Fig0203(a).tif');
[counts,x]=imhist(f,25);%计算有25个区间的直方图
[m,n]=size(f);%计算图像大小
counts=counts/m/n;%计算归一化直方图各区间的值
stem(x,counts);绘制归一化直方图

例绘制条形图

f=imread('Fig0203(a).tif');
h=imhist(f,25);%直方图,灰度级分为25,垂直量
horz=linspace(0,255,25);%将灰度级分为25份,水平分量
bar(horz,h)
axis([0 255 0 450000])
set(gca,'xtick',0:50:255)
set(gca,'ytick',0:50000:450000)

axis函数语法axis([horzmin horzmax vertmin vertmax])设定水平轴与垂直轴的最小值与最大值。后两句中的gca代表获取当前轴,xtick和ytick设置显示水平轴和垂直轴标尺。

直方图均衡

就是将图像中的灰度级发布平均,每个灰度级区间的元素数量相近,就可以使原图像的细节更加清晰。
使用histeq函数实现,语法形式q=histeq(f,nlev)f为输入图像,nlev是输出图像设定的灰度级,默认值是64.若nlev与L相等,则histeq直接执行变换函数,若nelv小于L,则histeq试图分配灰度值区间,从而得到近似平坦的直方图。
例 直方图均衡

% clf;
% clear;
% clc;
f=imread('Fig0208(a).tif');
subplot(2,2,1);
imshow(f);
subplot(2,2,2);
imhist(f);
ylim('auto');
g=histeq(f,256);
subplot(2,2,3);
imshow(g);
subplot(2,2,4);
imhist(g);
ylim('auto');

变换函数

hnorm=imhist(f)./numel(f);
cdf=cumsum(hnorm);
x=linspace(0,1,256);
plot(x,cdf);
axis([0 1 0 1]);
set(gca,'xtick',0:.2:1);
set(gca,'ytick',0:.2:1);
xlabel('input','fontsize',9);
ylabel('output','fontsize',9);

在这里插入图片描述

直方图匹配

就是将原始图像的直方图经过处理之后,改变为与目标变换函数相近的图像。
用到了histeq函数,语法形式j=histeq(i,hgram),其中i为输入图像,hgram为目标直方图的图像,j为经过处理后的图像。
例 将i的图像分别匹配到i1和i2的直方图。

clf;clear;clc;
i=imread('pout.tif');
i1=imread('coins.png');
i2=imread('circuit.tif');

hgram1=imhist(i1);
hgram2=imhist(i2);

j1=histeq(i,hgram1);
j2=histeq(i,hgram2);

subplot(2,5,1);
imshow(i);
subplot(2,5,2);
imshow(i1);
subplot(2,5,3);
imshow(i2);
subplot(2,5,4);
imshow(j1);
subplot(2,5,5);
imshow(j2);

subplot(2,5,6);
imhist(i);
subplot(2,5,7);
imhist(i1);
subplot(2,5,8);
imhist(i2);
subplot(2,5,9);
imhist(j1);
subplot(2,5,10);
imhist(j2);

在这里插入图片描述

2019-04-08 08:34:25 Dujing2019 阅读数 277

数字图像处理—灰度变换与空间滤波

(三)直方图处理与函数绘图

以从图像灰度直方图中提取的信息为基础的灰度变换函数,在诸如增强、压缩、分割、描述等方面的图像处理中起着重要作用。

3.1生成并绘制图像的直方图

在[0,G]范围内总共有L级可能灰度的一幅数字图像的直方图,定义为下列离散函数:
在这里插入图片描述
rkr_k是[0,G]间隔内的第k级灰度,nkn_k为图像中出现rkr_k这种灰度的像素数。对于uint8类,G的值为255;对于uint16类,G的值为65535;对于浮点图像类,G的值为1.0。注意,对于uint8和uint16类的图像,G=L-1。有时,利用归一化的直方图是必要的。用h(rk)h(r_k)的所有元素除以图像中的像素总数,就可以简单地得到归一化直方图:
在这里插入图片描述
其中,对整幅图像k=0, 1, 2, … , L-1。从基础概率论的角度讲,我们认可用p(rk)p(r_k)表示灰度级rkr_k出现的概率。

工具箱中用于处理图像直方图的核心函数是imhist,

基本语法如下:

h=imhist(f,b)       %f为输入图像,h为直方图,b是用来形成直方图的“统计堆栈”的数目(默认256)

举例描述:

如果我们处理一幅 uint8 类的图像且设 b = 2, 然后灰度范围被分成两部分: 0至 127和 128 至255。所得的直方图将有两个值:h (1) 等于图像在[0,127]间隔内的像素数,h (2) 等于图像在[128, 255] 间隔内的像素数。

通过下列表达式就可以得到归一化的直方图:

p = imhist(f, b) /numel(f)      %numel (f) 函数可以给出数组f中元素的个数 (也就是图像中的像素数)

计算并绘制图像直方图

1. 最简便方法是利用没有输出规定的imhist 函数

函数公式:

imhist(f);

代码编写:

imread('D:\数字图像处理\第二章学习\blue.jpg');          %读取图片文件中的数据
f=imread('D:\数字图像处理\第二章学习\blue.jpg');  
imhist(f);

运行结果如下:

左:原图                右 :直方图(a)

2. 用条形图绘制直方图

函数公式:

bar(horz, z, width)       %horz的值给出了水平增量,z的值对应垂直量,width 的值默认值为 0.8,当值为1时,竖条较明显;当值为 0时,竖条是垂直线。

代码编写:

f=imread('D:\数字图像处理\第二章学习\blue.jpg'); 
h = imhist(f);                         %生成直方图  
h1=h(1:10:256);                        %垂直量
horz = 1:10:256;                       %水平增量
figure,bar(horz, h1);                  %绘制条状直方图  
axis([0 255 0 60000]) ;                %axis([horzmin horzmax vertmin vertmax])  设置坐标轴最大最小值  
set(gca,'xtick',0:50:255);             %gca获得当前轴  xtick 和 ytick设置显示水平轴和垂直轴标尺
set(gca,'ytick',0:20000:60000);        %设置坐标轴的标尺  

运行效果如下:

左:原图                右 :条状直方图(b)

对比:

b图垂直标度比a图中整个直方 图的跨度范围宽,这是因为每个条的高度都由某个范围的所有像素决定,而不是由单个值的所有像素决定。

3. 用杆状图绘制直方图

函数公式:

 stem(horz,h, 'r--p') 

代码编写:

f=imread('D:\数字图像处理\第二章学习\dog3.jpg'); 
h = imhist(f,25);                            %生成直方图  
horz = linspace(0, 255, 25);                 %linspace(x1,x2,n)是生成从x1到x2的n个等距向量
stem(horz, h, 'fill');                       %绘制杆状直方图,如果使用了 fill, 那么标记点用三元组中第一个元素指定的颜色填充。默认蓝色,实线,圆圈。
axis([0 255 0 60000]);                       %axis([horzmin horzmax vertmin vertmax])  设置坐标轴最大最小值
set(gca, 'xtick', [0:50:255]);               %gca获得当前轴  xtick 和 ytick设置显示水平轴和垂直轴标尺
set(gca, 'ytick', [0:20000:60000]);          %设置坐标轴的标尺  

运行效果如下:

左:原图                右 :杆状直方图(c)

4. 直线绘制直方图

函数公式:

 plot(horz, z, 'LineSpec')     %horz由所有输入点坐标的x值组成,z是由与horz中包含的x对应的y所组成的向量。LineSpec是用户指定的绘图样式。

代码编写:

f=imread('D:\数字图像处理\第二章学习\dog3.jpg'); 
h = imhist(f);                              %生成直方图   
plot(h);                                    %绘制直方图,使用默认值
axis([0 255 0 60000]);                      %axis([horzmin horzmax vertmin vertmax])  设置坐标轴最大最小值
set(gca, 'xtick', [0:50:255]);              %gca获得当前轴  xtick 和 ytick设置显示水平轴和垂直轴标尺
set(gca, 'ytick', [0:20000:60000]);         %设置坐标轴的标尺 

运行效果如下:

左:原图                右 :直方图(d)

3.2直方图均衡化

假设灰度级为归一化在[0,1]范围内的连续量,让pr(r)p_r(r)代表一幅给定图像的灰度级的概率密度函数(PDF),下标用来区分输入图像和输出图像的概率密度函数。假设我们对输入灰度进行下列变换,得到输出(处理后的)灰度级s:
在这里插入图片描述
可以看出,输出灰度级的概率密度函数是均匀的,也就是:
在这里插入图片描述
当灰度级为离散值时,我们利用直方图并采用前面介绍的直方图均衡化技术。一般来说, 虽然由于变量的离散特性,处理后的图像直方图也不会完全均匀。对于离散的灰度级,我们采用求和的方式,将均衡化变换成为下列形式:
在这里插入图片描述
式中,k=0,1 , 2, …, L-1, 且sks_k是输出(处理后的)图像的灰度值,对应输入图像的灰度值为rkr_k

直方图均衡化由工具箱中的 histeq 函数实现,

语法如下:

g=histeq(f,nlev)     %f为输入图像,nlev为输出图像设定的灰度级数。

代码编写:

f=imread('D:\数字图像处理\第二章学习\dog1.jpg');           %读取图像
imshow(f);                                               %显示图像
figure;                                                  %创建新窗口
imhist(f);                                               %直方化图像
ylim('auto');                                            %自动设定纵坐标轴的取值范围和刻度线
g=histeq(f, 256);                                        %均衡化图像
figure;                                                  %创建新窗口
imshow(g);                                               %显示图像
figure;                                                  %创建新窗口
imhist(g);                                               %直方化被均衡化的图像

运行效果如下:

左:原图                右 :原图直方图(e)
左:均衡化后的图(f)                右 :图f的直方图(g)

分析:

均衡化处理后的图象只能是近似均匀分布。均衡化图象的动态范围扩大了,但其本质是扩大了量化间隔,而量化级别反而减少了,因此,原来灰度不同的象素经处理后可能变的相同,形成了一片的相同灰度的区域,各区域之间有明显的边界,从而出现了伪轮廓。

3.3直方图匹配化(规定化)

直方图均衡化通过把输入图像的灰度级扩展到较宽灰度范围来实现图像增强,但这种方法有时并不总能导致成功的结果。当图像中接近0的像素过多,进行直方图均衡的时候,会导致统计概率变大,直接映射到高灰度,直接导致图像整体变量,达不到原来想要的结果,此时就需要使用直方图匹配,让变化后的图像具有特定的直方图。有时候,我们为了使两幅图像的色调保持一致,也可以采用该方法。

这种方法在原理上很简单。考虑归一化之后在[0, 1]区间内的连续灰度级,令 r和z分别表 示输入图像与输出图像的灰度级。输入图像的灰度级有概率密度函数pr(r)p_r(r),输出图像的灰度级具有规定的概率密度函数pz(z)p_z(z)。变换为:
在这里插入图片描述
得到的灰度级s具有均勻的概率密度函数ps(s)p_s(s)。假设定义的变量z具有下列特性:

在这里插入图片描述
我们要寻找的是灰度级为 Z 的图像,且具有特定的概率密度pz(z)p_z(z)。由前面的两个等式可得:
在这里插入图片描述
可以由输入图像得到TrT_r(这是上面讨论的直方图均衡化变换),由此得出结论:只要找到 H-1, 就能利用前面的等式得到变换后的灰度级z,概率密度函数(PDF)为指定的pz(z)p_z(z)

语法如下:

g = histeq(f,hspec)     %f 为输入图像,hspec为特定的直方图(某个特定值的行向量),g为输出图像。

histeq 的特性是当 length (hspec) 比图像 f 中的灰度级小很多时,图像 g 的直方图通常会较好地匹配 hspec。

代码编写:

f = imread('D:\数字图像处理\第二章学习\dog2.jpg');
g = imread('D:\数字图像处理\第二章学习\blue.jpg');
g1 = imhist(g);                                 %生成直方图  
match = histeq(f, g1);                          %得到匹配后的图像
figure;
subplot(2, 3, 1), imshow(f), title('原图像');
subplot(2, 3, 2), imshow(g), title('模板图像');
subplot(2, 3, 3), imshow(match), title('匹配后的图像');
subplot(2, 3, 4), imhist(f), title('原图像的直方图');
subplot(2, 3, 5), imhist(g), title('模板图像的直方图');
subplot(2, 3, 6), imhist(match), title('匹配后得到图像对应的直方图');

运行状态如下:
在这里插入图片描述

3.4 函数 adapthisteq

这个工具箱函数执行所谓的对比度受限的自适应直方图均衡。这个方法是由用直方图规定化方法处理图像的小区域(称为小片)组成。然后用双线性内插将相邻小片组合起来以消除人工引入的边界效应。特别是可以限制均匀亮度区域的对比度, 以免放大噪声。

语法如下:

g = adapthisteq(f, paraml, vail, param2, val2, ...)            %f是输入图像,g是输出图像

代码编写:

g= imread('D:\数字图像处理\第二章学习\dog2.jpg');
f = rgb2gray(imread('D:\数字图像处理\第二章学习\dog2.jpg'));
g1 = adapthisteq(f);
g2 = adapthisteq(f, 'NumTiles', [25 25]);
g3 = adapthisteq(f, 'NumTiles', [25 25], 'ClipLimit', 0.05);
figure;
subplot(2, 5, 1), imshow(g), title('彩色图像');
subplot(2, 5, 2), imshow(f), title('灰度图像');
subplot(2, 5, 3), imshow(g1), title('用默认值使用adapthisteq的效果');
subplot(2, 5, 4), imshow(g2), title('将参数NumTiles设置为[25 25]的效果');
subplot(2, 5, 5), imshow(g3), title('将参数ClipLimit设置为0.05的效果');
subplot(2, 5, 6), imhist(g), title('直方图(上)');
subplot(2, 5, 7), imhist(f), title('直方图(上)');
subplot(2, 5, 8), imhist(g1), title('直方图(上)');
subplot(2, 5, 9), imhist(g2), title('直方图(上)');
subplot(2, 5, 10), imhist(g3), title('直方图(上)');

纠结这个代码出错已经两个小时了,期间尝试过很多解决方案,都无果,后来认真理解了公式,这有一个很容易出错却很难发现的点,可能真的是我刚接触图像处理,这个函数adapthisteq(f)中的f是输入图像,但是f要求是二维矩阵,而这个在刚萨雷斯课本中并没有提到,二维矩阵只能表示灰度图片,所以,如果jpg是彩色的,要用rgb2gray 转换为灰度图片才可以,注意!注意!注意!

运行状态如下:
在这里插入图片描述
分析:

使用函数 adapthisteq 全部默认设置之后的结果:虽然结果显示的细节略有增加,但图像的重要部分仍然较暗。将小片大小谱加到[25 25]后的结果:清晰度略有增加,但并未出现新的细节。将参数ClipLimit设置为0.05的效果:与前两个结果相比,这幅图像在细节方面明显增强。通过比较这两幅图可以十分清楚地看到局部增强方法相对于全局增强方法的优势。

2018-05-07 15:21:31 weixin_42072280 阅读数 14158

灰度直方图

 灰度直方图描述了一幅图像的绘图统计信息,主要应用于图像分割和图像灰度变换等处理过程中。从数学上说它是一个关于灰度的函数,如令x表示灰度值(一般0≤x≤255),则f(x)表示当x为特定灰度时,一幅图像上灰度值为x的像素的数量,要注意的是这里的函数f(x)是一个离散的函数。从图形上来说,灰度直方图就是一个二维图,横坐标表示灰度值(灰度级别),纵坐标表示具有各个灰度值或者灰度级别的像素在图像中出现的次数或者概率。

imhist函数:计算图像直方图函数

具体用法: 

imhist( i ):直接显示图像i的灰度直方图(默认为255个灰度级); 
imhist(i,n):n为指定灰度级显示直方图; 
[count, x] = imhist( i ) 获取直方图信息,count为每一级灰度像素个数,x为灰度级,x也可以在imhist(i,x)中指定,可以通过stem(x,count)画相应直方图;

代码示例

clc;clear all;close all;

I = imread('cameraman.tif');
figure;
imshow(I);
title('source');

figure;
subplot(221);imhist(I,2);
subplot(222);imhist(I,5);
subplot(223);imhist(I,10);
subplot(224);imhist(I);

figure;
subplot(121); imhist(I,10)
[count,x] = imhist(I,10)
subplot(122);stem(x,count);

结果如下



由此可见,柱状图的峰值出现在0和170附近,这是因为图片中的主要颜色分别为人物衣服的黑色和天空的灰色。



[count,x] = imhist(I,10)
上述代码的运行结果如下:

count =
        9008
        5530
        1957
        2181
        7801
       12551
       23404
        2576
         436
          92
x =
         0
   28.3333
   56.6667
   85.0000
  113.3333
  141.6667
  170.0000
  198.3333
  226.6667
  255.0000

输出结果共10个,x代表灰度值,count为每一级灰度像素个数


参考博客:

https://blog.csdn.net/artprog/article/details/49747173

https://blog.csdn.net/ahafg/article/details/48676543








2017-09-23 21:03:53 abc1942227359 阅读数 454

imhist

利用matlab计算图像直方图函数为imhist() 
具体用法: 
imhist( i );直接显示图像i的灰度直方图; 
imhist(i,n)n为指定灰度级显示直方图; 
[count, x] = imhist( i ) 获取直方图信息,count为每一级灰度像素个数,x为灰度级,x也可以在imhist(i,x)中指定,可以通过stem(x,count)画相应直方图;

没有更多推荐了,返回首页