2019-02-18 10:20:11 qq_34725005 阅读数 113
import matplotlib.pyplot as plt
import numpy as np
import cv2

def convert(r):
    x = np.zeros([256])
    for i in range(r.shape[0]):
        for j in range(r.shape[1]):
            x[r[i][j]]+=1
    x = x/r.size
    sum_x = np.zeros([256])
    for i,_ in enumerate(x):
        sum_x[i] = sum(x[:i])
    s = np.empty(r.shape,dtype=np.uint8)
    for i in range(r.shape[0]):
        for j in range(r.shape[1]):
            s[i][j] = 255 * sum_x[r[i][j]]
    return s

im = cv2.imread('tetet.jpg')
im_mat = np.asarray(im)

#原直方图
plt.hist(im_mat.reshape([im_mat.size]),256,density=1)
plt.show()

#均衡化直方图
im_converted_mat = convert(im)
plt.hist(im_converted_mat.reshape([im_converted_mat.size]),256,density=1)
plt.show()

#均衡化图
cv2.imshow('original',im)
cv2.imshow('jpg',im_converted_mat)
cv2.waitKey()
2018-04-24 11:40:18 u010936286 阅读数 400

图像的直方图

图像的直方图处理是从概率统计的角度出发,对图像灰度级的概率分布进行变换,从而达到使图像细节丰富、动态范围较大、便于观测和理解的目的。

直方图处理是多种空间域处理技术的基础,可以直接用于图像的增强以及图像的压缩和分割。在灰度级范围为[0,L-1]的数字图像的直方图可以表示为:


其中rk是第k级灰度值,nk是图像中灰度为rk的像素的个数,MN分别是图像的行和列数。

我们首先对下列图像进行观测。我们可以看到,在亮图像中,直方图的分量集中在灰度级的高端,而在暗图像中,中直方图的分量倾向于灰度级的低端。低对比度的图像具有较窄的直方图,且集中于灰度级的中部。对于单色图像,这就意味着暗淡,好像灰度被冲淡了一样。而高对比度的图像的直方图的分量覆盖了很宽的灰度级范围,而且像素的分布比较均匀。因此,若一幅图像的像素倾向于占据整个可能的灰度级并且分布均匀,那么该图像会有高对比度的外观并展示灰色调的较大变化。最终效果将是一幅灰度细节丰富且动态范围较大的图像。


下面是图像直方图绘制的Matlab程序,其中numel(image)是求取图像的M×N的值,imhist是求取图像的直方图,这里进行了归一化处理,使每个值处于[0,1]范围内。bar()用于显示直方图。

clear
clc
%%读取图像数据
Cells_bright=imread('细胞亮.jpg');
Cells_dark=imread('细胞暗.jpg');
Cells_low_contrast=imread('细胞低对比度.jpg');
Cells_hight_contrast=imread('细胞高对比度.jpg');

%%灰度化
Cells_bright_gray=rgb2gray(Cells_bright);
Cells_dark_gray=rgb2gray(Cells_dark);
Cells_low_contrast_gray=rgb2gray(Cells_low_contrast);
Cells_hight_contrast_gray=rgb2gray(Cells_hight_contrast);

%%求直方图
h_bright         =imhist(Cells_bright_gray)/numel(Cells_bright_gray);
h_dark           =imhist(Cells_dark_gray)/numel(Cells_dark_gray);
h_low_contrast   =imhist(Cells_low_contrast_gray)/numel(Cells_low_contrast_gray);
h_hight_contrast =imhist(Cells_hight_contrast_gray)/numel(Cells_hight_contrast_gray);

%%绘制直方图
h=0:255;
figure(1)
subplot(1,2,1)
imshow(Cells_bright)
title('细胞亮')
subplot(1,2,2)
bar(h,h_bright);
title('直方图')
axis([0,255,0,0.1])

figure(2)
subplot(1,2,1)
imshow(Cells_dark_gray)
title('细胞暗')
subplot(1,2,2)
bar(h,h_dark);
title('直方图')
axis([0,255,0,0.1])

figure(3)
subplot(1,2,1)
imshow(Cells_low_contrast_gray)
title('细胞低对比度')
subplot(1,2,2)
bar(h,h_low_contrast);
title('直方图')
axis([0,255,0,0.1])

figure(4)
subplot(1,2,1)
imshow(Cells_hight_contrast_gray)
title('细胞高对比度')
subplot(1,2,2)
bar(h,h_hight_contrast);
title('直方图')
axis([0,255,0,0.1])

图像的直方图均衡




注意,我们的目的是为了使图像的直方图分量覆盖整个灰度级且分布均匀,因此其等价于使得Ps(s)的直方图分布律为:


因此利用上述两个公式可以得到:



可以看到,变换后的图像的直方图概率分布为均匀分布。

对于离散的数字图像可以通过下式进行变换。


下面是原书中给的一个例子:


下面我们以图像“细胞亮”为实例,通过Matlab实现图像的均衡。这里的histeq可以实现对原图像的直方图均衡。我们可以看到,直方图均衡后的图像显示了更多细节,且直方图分量分布更加均匀。

%%直方图均衡
hist_equilibrium=histeq(Cells_bright_gray);

%%直方图
Image_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium);
%%绘制直方图均衡后图像
figure(5)
subplot(1,2,1)
imshow(g)
title('细胞亮直方图均衡后的图片')
subplot(1,2,2)
bar(h,Image_equilibrium_hist);
title('直方图')
axis([0,255,0,0.1])

直方图规定化

上述我们实现了对某张图像进行直方图均衡,使图像的直方图分量分布均匀。但是有时对图像进行直方图均衡效果不佳。例如:

clear
clc
%%读取图像数据
Mars=imread('火星.jpg');

%%灰度化
Mars_gray=rgb2gray(Mars);

%%直方图
h=0:255;
h_Mars=imhist(Mars_gray)/numel(Mars_gray);
figure(1)
subplot(1,2,1)
imshow(Mars_gray)
title('火星灰度图')
subplot(1,2,2)
bar(h,h_Mars);
title('直方图')
axis([0,255,0,1])

%%直方图均衡
hist_equilibrium=histeq(Mars_gray);
Mars_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium);
figure(2)
subplot(1,2,1)
imshow(hist_equilibrium)
title('火星直方图均衡')
subplot(1,2,2)
bar(h,Mars_equilibrium_hist);
title('直方图')
axis([0,255,0,1])
如图显示了火星卫星(Phobos)的图像,图像中的大部分是暗色区域,如果我们采用直方图均衡的方式进行图像增强,会使得把非常窄的暗像素区域映射到输出图像灰度级的高端。直方图的规定化就是解决这类问题。

直方图的规定化可以理解为指定一种直方图分布律(自己可以根据实际需要设计),将原图像的直方图分布变换为我们规定的分布律。其实现方式也是显而易见的,由于直方图均衡是一一对应的结果,因此原图像可以通过直方图均衡由P(r)→P(s)(再次强调是一一对应的),同理,我们设计的直方图分布律也可以进行直方图均衡P(z)→P(s),而由于直方图均衡的一一对应的特性,我们可以找到这样的映射:P(s)→P(z)。因此我们可以通过这样的路线实现直方图规定化。

(1)P(r)→P(s)

(2)P(z)→P(s),P(s)→P(z)

(3)P(r)→P(s)→P(z)

下面是原书中的示例:


下面我们对上述火星卫星图像进行直方图规定化操作:

%%指定直方图分布律
p(1:100)=-16/50/50*(h(1:100)-50).^2+18;
p(101:256)=2;
p=p/sum(p);
figure(3)
plot(h,p);
title('指定的直方图')

%%直方图匹配
hist_matching=histeq(Mars_gray,p);
Mars_matching_hist=imhist(hist_matching)/numel(hist_matching);
figure(4)
subplot(1,2,1)
imshow(hist_matching)
title('火星直方图匹配')
subplot(1,2,2)
bar(h,Mars_matching_hist);
title('直方图')
axis([0,255,0,1])

我们可以看到直方图规定化具有较好的效果。

局部直方图均衡

局部直方图均衡是为了解决在全局处理情况下使得图像大面积引入噪声的问题。例如下图所示。这里可以通过在某个局部邻域内进行均衡操作。具体代码可以参考后面讲解的直方图统计进行局部修改。


直方图统计

直方图统计的方式增强图像是借助图像中的数据的统计量进行分析计算。例如图像的平均值和二阶矩(方差)等统计量。

图像的取样均值可以表示为:


方差可以表示为:


其中均值表示了图像整体的明暗程度,方差可以理解为图像中的对比度。

例如下面是一幅放大了约130倍钨丝的SME图像,可以看到图像中央的钨丝及其支架可以很清楚并容易的分析,然而图像的右侧存在的另一根钨丝的结构由于过暗而不宜观测。倘若我们希望图像中央钨丝结构不变,仅仅对暗区纹理部分进行增强,而图像的全局均衡化虽然对暗区进行了增强,却影响了中央钨丝的区域。这时我们可以通过图像的直方图统计的方式实现。

clear
clc
%%读取图像数据
Tungsten=imread('放大约130倍钨丝的SME图像.jpg');

%%灰度化
Tungsten_gray=rgb2gray(Tungsten);

%%直方图
h=0:255;
h_Tungsten=imhist(Tungsten_gray)/numel(Tungsten_gray);
%%绘制直方图
figure(1)
subplot(1,2,1)
imshow(Tungsten_gray)
title('放大约130倍钨丝的SME图像')
subplot(1,2,2)
bar(h,h_Tungsten);
title('直方图')
axis([0,255,0,0.1])

%%全局直方图均衡
hist_equilibrium=histeq(Tungsten_gray);
Tungsten_equilibrium_hist=imhist(hist_equilibrium)/numel(hist_equilibrium);
figure(2)
subplot(1,2,1)
imshow(hist_equilibrium)
title('全局直方图均衡')
subplot(1,2,2)
bar(h,Tungsten_equilibrium_hist);
title('直方图')
axis([0,255,0,1])


具体做法如下,首先取某个大小为n×n的邻域,求取其均值和标准差,若其均值小于平均值的k0倍,则说明该区域过暗,可以表示为:

若考虑该区域的对比度,则通过以下公式:

K2>1则表示增强亮区域,若k2<1则表示增强暗区域。
当然,我们需要限制能够接受的最低的对比度值,否则该过程会试图增强标准差为0的恒定区域。

对于满足上述所有条件的区域,可以通过将该像素值乘以指定常数E来处理,以便增强或减小该区域灰度值。

因此,综上所述,我们可以表示为:


下面对上述钨丝图进行操作:

首先求取全局均值和标准差,其次设置k0、k1、k2和E,设置邻域范围为n=3。这里的wextend()用于扩展图像,否则图像的边缘点,如点(1,1)无法得到计算。然后根据上述公式进行计算。可以看到通过直方图统计的方式增强了图像右侧的暗区域。

%%直方图统计
Tungsten_gray=double(Tungsten_gray);    %格式转化,便于后期计算
Tungsten_mean_G =mean(Tungsten_gray(:));  %全局平均值
k0=0.25;
Tungsten_std_G=std(Tungsten_gray(:));   %全局标准差
k2=0.4;
k1=0.02;
E=4.0;
if k1>=k2
    disp(['输入错误,k1>k2'])
end

n=3;    %局部均衡邻域范围
st=floor(n/2);           %以像素所在位置为(2,2)为例,其邻域为[1:3,1:3]。
image_extend=wextend('2D','sym',Tungsten_gray,n);%%扩展
Tungsten_result=Tungsten_gray;              %用于得到结果
[row,col]=size(image_extend);              %扩展后的图像大小
for i=1+n:row-n
    for j=1+n:col-n
        img_temp=image_extend(i-st:i+st,j-st:j+st);   %获取像素(i,j)的邻域
        img_temp_mean=mean(img_temp(:));         %求局部均值
        img_temp_std=std(img_temp(:));           %求局部标准差
        if img_temp_mean<=k0*Tungsten_mean_G && img_temp_std<=k2*Tungsten_std_G &&img_temp_std>=k1*Tungsten_std_G;
            Tungsten_result(i-n,j-n)=img_temp(st+1,st+1)*E;  %将该像素增强E倍
        end
        
    end
end
Tungsten_result=uint8(Tungsten_result);
Tungsten_result_hist=imhist(Tungsten_result)/numel(Tungsten_result);
figure(3)
subplot(1,2,1)
imshow(Tungsten_result)
title('局部直方图统计增强后的图像')
subplot(1,2,2)
bar(h,Tungsten_result_hist);
title('直方图')
axis([0,255,0,0.1])

改变参数,可以得到下图。
k0=0.4;
k2=0.4;
k1=0.02;
E=4.0;

我们也可以仅对右侧一半进行局部直方图统计增强。使j加了列数的一半。则可以得到下图。

j=1+n+floor(col/2):col-n

2019-07-21 23:12:46 u012292754 阅读数 171

1 Image Histtogram

在这里插入图片描述

1.1 画直方图

  • HistogramFilter
package demo2.histogram;

import demo2.utils.AbstractImageOptionFilter;

import java.awt.image.BufferedImage;
import java.util.Arrays;

public class HistogramFilter extends AbstractImageOptionFilter {
    private int[] histData;

    public HistogramFilter() {
        histData = new int[256];
    }

    public int[] getHistData() {
        return histData;
    }

    public void setHistData(int[] histData) {
        this.histData = histData;
    }

    @Override
    public BufferedImage process(BufferedImage src) {
        int width = src.getWidth();
        int height = src.getHeight();
        int[] pixels = new int[width * height];
        getRGB(src, 0, 0, width, height, pixels);
        int index = 0;
        Arrays.fill(histData, 0);
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                index = row * width + col;
                int pixel = pixels[index];
                int tr = (pixel >> 16) & 0xff; // red
                histData[tr]++;
            }
        }

        return src;
    }
}

  • ImagePanel
package demo2.histogram;

import demo2.coloradjust.ColorAdjustFilter;

import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

public class ImagePanel extends JComponent implements ActionListener {

    private BufferedImage image;

    private JButton processBtn;

    private int[] histdata;

    public ImagePanel(BufferedImage image) {
        this.image = image;
    }

    public JButton getButton() {
        processBtn = new JButton("按钮");
        processBtn.addActionListener(this);

        return processBtn;
    }

    @Override
    protected void paintComponent(Graphics g) {
        Graphics2D g2d = (Graphics2D) g;
        if (null != image) {
            g2d.drawImage(image, 0, 0, image.getWidth(), image.getHeight(), null);
        }

        if (histdata != null) {
            int xstart = image.getWidth() + 50;
            int ystart = image.getHeight();

            g2d.setPaint(Color.BLACK);
            g2d.drawLine(xstart, 0, xstart, ystart); // Y 轴
            g2d.drawLine(xstart, ystart, xstart + 256, ystart); // x轴

            // find max value
            int max = -1;
            int min = 0;
            for (int i = 0; i < histdata.length; i++) {
                max = Math.max(max, histdata[i]);
            }

            float delta = max - min;
            g2d.setPaint(Color.YELLOW);
            for (int i = 0; i < histdata.length; i++) {
                float v1 = histdata[i] - min;
                int value = (int) ((v1 / delta) * 256);
                g2d.drawLine(xstart + i + 1, ystart, xstart + i + 1, ystart - value);
            }

        }

    }

    @Override
    public void actionPerformed(ActionEvent e) {
        if (e.getSource() == processBtn) {
            this.process();
            this.repaint();
        }
    }

    public void process() {
        HistogramFilter filter = new HistogramFilter();
        filter.process(this.image);
        histdata = filter.getHistData();

        for (int i = 0; i < histdata.length; i++) {
            System.out.println("灰度值" + i + ":" + histdata[i]);
        }
    }


    public static void main(String[] args) {
        File file = new File("resource/gray.jpg");

        try {
            BufferedImage image = ImageIO.read(file);
            JFrame frame = new JFrame();
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            ImagePanel imp = new ImagePanel(image);
            frame.getContentPane().add(imp, BorderLayout.CENTER);

            JPanel flowPanel = new JPanel();
            flowPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
            flowPanel.add(imp.getButton());

            frame.getContentPane().add(flowPanel, BorderLayout.SOUTH);
            frame.setSize(500, 400);
            frame.setTitle("图像显示测试");
            frame.setVisible(true);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

}

在这里插入图片描述

2 直方图均衡化

  • 均衡化公式
  • r: 输入图像的灰度级别
  • s: 输出图像的灰度级别
    在这里插入图片描述

  • 直方图数据到均衡化
    在这里插入图片描述

  • HistgramBalanceFilter
package demo2.histogrambalance;

import demo2.utils.AbstractImageOptionFilter;

import java.awt.image.BufferedImage;
import java.util.Arrays;

public class HistgramBalanceFilter extends AbstractImageOptionFilter {
    @Override
    public BufferedImage process(BufferedImage src) {
        int width = src.getWidth();
        int height = src.getHeight();
        int[] pixels = new int[width * height];
        int[] output = new int[width * height];
        getRGB(src, 0, 0, width, height, pixels);
        BufferedImage dest = createCompatibleDestImage(src, src.getColorModel());
        int index = 0;
        double[] histData = new double[256];
        Arrays.fill(histData, 0);
        for (int row = 0; row < height; row++) {
            for (int col = 0; col < width; col++) {
                index = row * width + col;
                int pixel = pixels[index];
                int tr = (pixel >> 16) & 0xff; // red
                histData[tr]++;
            }
        }

        // 归一化,变成 0-1 之间的数据
        double total = pixels.length;
        for(int i=0; i<histData.length; i++) {
            histData[i] = histData[i] / total;
        }

        // setup lookup table
        int[] lut = new int[256];
        for(int i=0; i<lut.length; i++) {
            double sum = 0.0;
            for(int j=0; j<=i; j++) {
                sum += histData[j];
            }
            lut[i] = (int)Math.floor(sum * 255 + 0.5);
        }


        // 直方图均衡化
        for(int row=0; row<height; row++) {
            for(int col=0; col<width; col++) {
                index = row * width + col;
                int pixel = pixels[index];
                int tr = (pixel >> 16) & 0xff;
                output[index] = (0xff << 24 | lut[tr] << 16 | lut[tr] << 8 | lut[tr]);
            }
        }

        setRGB(dest, 0, 0, width, height, output);
        return dest;
    }
}

2019-09-02 21:16:05 weixin_44225182 阅读数 291

图像直方图归一化

图像直方图概念:

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

图像灰度直方图:一副数字图像有[0~255]灰度级,直方图定义如下:

其中,是第k个灰度级(如:255),是该灰度级的个数。
归一化直方图定义如下:

即:第k个灰度级出现的数量,比上所有灰度级数量总和,也就是概率

获得图像直方图

t=imread('a1.jpg')
subplot(1,2,1),imshow(t),title('原图')
subplot(1,2,2),imhist(t),title('图像直方图')

效果图:
在这里插入图片描述

Imhist
该函数用于获取图像数据直方图。在图像增强技术中,图像灰度级直方图有着重要的意义,是直方图修改技术、直方图均衡化等一些图像处理技术的基础。在matlab 的命令窗口中键入doc imhist或help imhist即可获得该函数的帮助信息。

调用格式:

imhist(I,n)
imhist(X,map)
[counts,x] = imhist(I)
说明:imhist(I,n)其中,I为灰度的输入图像,n为指定的灰度级数目,缺省值为256;imhist(X,map)计算和显示索引色图像X的直方图,map为调色板。用stem(x,counts)同样可以显示直方图。counts和x分别为返回直方图数据向量和相应的彩色向量。

这里着重说一下imhist(I,n)的用法:
验证代码:

 t=imread('a1.jpg')
subplot(2,3,1),imshow(t),title('原图')
subplot(2,3,2),imhist(t),title('灰度级数默认:256')
subplot(2,3,3),imhist(t,128),title('灰度级数:128')
subplot(2,3,4),imhist(t,64),title('灰度级数:64')
subplot(2,3,5),imhist(t,32),title('灰度级数:32')
subplot(2,3,6),imhist(t,16),title('灰度级数:16')

结果图
在这里插入图片描述
总结imhist(I,n):

n的定义是灰度级数,这里我们可以理解为将0~255分成几份,比如默认为256,就是分成256份,一份是1,所以灰度值每隔1就统计一次;又n为128,则把0-255分成128份,一份为2,灰度值每隔2统计一次,所以从对比图像看,n为128的看起来比n为256的更稀疏。

[counts,x] = imhist(I)这句话的意思是,获取直方图的横坐标和纵坐标,即各个像素级,以及每个像素级上的像素出现的次数,这个有个易错点,就是,counts其实是直方图的纵坐标值,而x才是直方图的横坐标。

那么获得这两个值有什么用呢? 这里是可以利用这两个值,用stem函数绘出统计图像

上代码:

F=imread('a1.jpg');
I=rgb2gray(F);
subplot(1,3,1),imshow(I),title('原图')
subplot(1,3,2),imhist(I),title('原图的图像直方图')
[count,x]=imhist(I)
% 获取直方图的横坐标和纵坐标,即各个像素级,以及每个像素级上的像素出现的次数 counts:纵坐标 x:横坐标
subplot(1,3,3),stem(x,count),title('根据图像直方图绘制的统计图')
% 通过刚才得到的值,绘制条形图。

效果图:
在这里插入图片描述
这里看出stem绘出的图像和imhist绘出的图像其实是一样的,只是stem绘出的图像统计了次数。

如果这里我们需要将图像直方图归一化,其实就是将纵坐标变成当前次数占总次数的概率,这个也很简单,就需要将stem的counts先除以总像素数量就行。
代码:

F=imread('a1.jpg');
I=rgb2gray(F);
[m,n]=size(I)
subplot(1,4,1),imshow(I),title('原图')
subplot(1,4,2),imhist(I),title('原图的图像直方图')
[count,x]=imhist(I)
subplot(1,4,3),stem(x,count),title('根据图像直方图绘制的统计图')
count=count/m/n
% 获取直方图的横坐标和纵坐标,即各个像素级,以及每个像素级上的像素出现的次数 counts:纵坐标 x:横坐标
subplot(1,4,4),stem(x,count),title('图像直方图归一化')

效果图:
在这里插入图片描述

2019-09-03 15:43:01 weixin_44225182 阅读数 770

图像直方图均衡化

首先,我们要理解什么是图像直方图均衡化:

把原始图像的灰度直方图从比较集中的某个灰度区间变成在全部灰度范围内的均匀分布。直方图均衡化就是对图像进行非线性拉伸,重新分配图像像素值,使一定灰度范围内的像素数量大致相同。直方图均衡化就是把给定图像的直方图分布改变成“均匀”分布直方图分布,具体见下图(说的简单点,就是把原来的图像的灰度分配均匀,使得0-255都有一定的取值,这样对比度相对大一些,视觉上更好看一点):在这里插入图片描述
这里我们可以直接利用histeq()、adapthisteq()函数对图像进行均衡化

 H= imread('a1.jpg'); 
if length(size(H))>2
    H=rgb2gray(H);  
end
subplot(3,2,1);  
imshow(H); title('原图');  
subplot(3,2,2);  
imhist(H); title('原图直方图');  
subplot(3,2,3);  
H1=adapthisteq(H);  
imshow(H1); title('adapthisteq均衡后图');  
subplot(3,2,4);  
imhist(H1);title('adapthisteq均衡后直方图');  
subplot(3,2,5);  
H2=histeq(H);  
imshow(H2); title('histeq均衡后图');  
subplot(3,2,6);  
imhist(H1); title('histeq均衡后直方图'); 

效果图:
在这里插入图片描述

当然,我们也可以自己编写均衡化函数,首先就要了解均衡化的算法步骤(这里我就不多说了)
上代码:

H= imread('a1.jpg'); 

%判断是否为三通道彩色图片 若是 则将其灰度化
if length(size(H))>2
    H=rgb2gray(H);  
end

%获取图片的尺寸 便于计算总像素数 即m*n 
[m,n]=size(H);  

%生成一个一行256列的矩阵
p=zeros(1,256);  

% 统计各灰度的像素个数 
%find(H==i) 是在图像矩阵里面寻找灰度为i的点坐标 
% 因为矩阵是从1开始的 所以为p(i+1)
for i=0:255  
   p(i+1)=length(find(H==i))/(m*n);  
end  


subplot(2,2,1);  
imshow(H);  
title('原图');  
subplot(2,2,2);  
% 显示原图的直方图
bar(0:255,p,'b');  
title('原图直方图');  
 
 % 利用循环 累加概率值
s=zeros(1,256);  
for i=1:256  
     for j=1:i  
         s(i)=p(j)+s(i);                  
     end  
end  

%对s中的数先乘以255,再取整   
a=round(s*255);  
b=H;  
%更新原图像的灰度
for i=0:255  
     b(find(H==i))=a(i+1);                
end
  
subplot(2,2,3);  
imshow(b)                            
title('均衡化后图像');  
 %统计更新后的概率
for i=0:255  
    GPeq(i+1)=sum(p(find(a==i)));            
end  
subplot(2,2,4);  
bar(0:255,GPeq,'b'); title('均衡化后的直方图'); 

效果图:
在这里插入图片描述

方法二(从大佬那里copy的)

Img= imread('a1.jpg'); 
if length(size(Img))>2
    Img=rgb2gray(Img);  
end
 
%绘制原始图像的直方图
[height,width]=size(Img);  
[counts1, x] = imhist(Img,256);  
counts2 = counts1/height/width;
figure(1),
subplot(1,2,1),
imshow(Img);title('原始图像');
subplot(1,2,2),
stem(x, counts2); title('原始图像直方图');
 
%统计每个灰度的像素值累计数目
NumPixel = zeros(1,256);%统计各灰度数目,共256个灰度级  
for i = 1:height  
    for j = 1: width  
    %对应灰度值像素点数量+1  
    %NumPixel的下标是从1开始,而图像像素的取值范围是0~255,所以用NumPixel(Img(i,j) + 1)  
    NumPixel(Img(i,j) + 1) = NumPixel(Img(i,j) + 1) + 1;  
    end  
end  
 
%将频数值算为频率
ProbPixel = zeros(1,256);  
for i = 1:256  
    ProbPixel(i) = NumPixel(i) / (height * width * 1.0);  
end  
 
%函数cumsum来计算cdf,并将频率(取值范围是0.0~1.0)映射到0~255的无符号整数
CumuPixel = cumsum(ProbPixel);  
CumuPixel = uint8(255 .* CumuPixel + 0.5); 
 
%直方图均衡。赋值语句右端,Img(i,j)被用来作为CumuPixel的索引
for i = 1:height  
    for j = 1: width  
        Img(i,j) = CumuPixel(Img(i,j)+1);  
    end  
end  
 
%显示更新后的直方图
figure(2),
subplot(1,2,1),
imshow(Img); title('直方图均衡化图像'); 
[counts1, x] = imhist(Img,256);  
counts2 = counts1/height/width;  
subplot(1,2,2),
stem(x, counts2); title('直方图均衡化后图像的直方图');

上面都是对灰度图片进行均衡化,那么对彩色图片怎么均衡化呢?办法肯定是有的。我们知道,彩色图片无非就是RGB三通道组成的,只要我们分别对三个通道进行均衡化,再合成,得到的图片就是彩色的,均衡化后的。
上代码:

Img= imread('a1.jpg'); 
OutImg=Img;
%分别提取三通道的信息
R = Img(:,:,1);  
G = Img(:,:,2);  
B = Img(:,:,3);  

%分别对三通道的图片进行均衡化 
R = histeq(R, 256);  
G = histeq(G, 256);  
B = histeq(B, 256);  
 
 %最后合成为一张图片
OutImg(:,:,1) = R;  
OutImg(:,:,2) = G;  
OutImg(:,:,3) = B;  
 
figure,
subplot(1,2,1),
imshow(Img);title('原始图像');
subplot(1,2,2),
imshow(OutImg); title('均衡化后结果');

效果图(感觉颜色更加丰富了,哈哈):
在这里插入图片描述
这里其实还有一种方法,就是先把RGB转换为HSV,再均衡化
上代码:

mg= imread('a1.jpg'); 
hsvImg = rgb2hsv(Img);  
V=hsvImg(:,:,3);  
[height,width]=size(V);  
 
V = uint8(V*255);  
NumPixel = zeros(1,256);  
for i = 1:height  
    for j = 1: width  
    NumPixel(V(i,j) + 1) = NumPixel(V(i,j) + 1) + 1;  
    end  
end  
 
ProbPixel = zeros(1,256);  
for i = 1:256  
    ProbPixel(i) = NumPixel(i) / (height * width * 1.0);  
end  
 
CumuPixel = cumsum(ProbPixel);  
CumuPixel = uint8(255 .* CumuPixel + 0.5);  
 
for i = 1:height  
    for j = 1: width  
        V(i,j) = CumuPixel(V(i,j)+1);  %注意,这里需要+1,要不然会出问题
    end  
end  
 
V = im2double(V);  
hsvImg(:,:,3) = V;  
outputImg = hsv2rgb(hsvImg);  
figure,
subplot(1,2,1),
imshow(Img);title('原始图像');
subplot(1,2,2),
imshow(outputImg); title('在HSV空间均衡化后结果');

效果图(感觉没有上一种方法好看,这个其实是要分图片的):
在这里插入图片描述

更多

获取更多资料、代码,微信公众号:海轰Pro
回复 海轰 即可

Matlab数字图像处理——直方图匹配

博文 来自: weixin_43262648

直方图均衡C实现

博文 来自: guo8113
没有更多推荐了,返回首页