图像直方图均衡方法(python和matlab实现代码)

        最近在学习图像对比度增强,其中一个基本的方法就是图像均衡化,了解并按照大佬的例子写了下自己的彩色图像的均衡化代码,于是记录下学习的结果.

图像直方图均衡化的介绍

        直方图均衡化是一种简单有效的图像增强技术,通过改变图像的直方图的分布来改变图像中各像素的灰度,主要用于增强动态范围偏小的图像的对比度。原始图像由于其灰度分布可能集中在较窄的区间,造成图像不够清晰。例如,过曝光图像的灰度级集中在高亮度范围内,而曝光不足将使图像灰度级集中在低亮度范围内。采用直方图均衡化,可以把原始图像的直方图变换为均匀分布(均衡)的形式,这样就增加了像素之间灰度值差别的动态范围,从而达到增强图像整体对比度的效果。换言之,直方图均衡化的基本原理是:对在图像中像素个数多的灰度值(即对画面起主要作用的灰度值)进行展宽,而对像素个数少的灰度值(即对画面不起主要作用的灰度值)进行归并,从而增大对比度,使图像清晰,达到增强的目的。

更详细的介绍可见:(26条消息) 【图像处理算法】直方图均衡化_桂哥317的博客-CSDN博客_直方图均衡化

 图像直方图均衡化方法流程:

1.统计出图像的直方图.

2.计算出各个灰度值像素的概率hist[i](i=1:256),每个灰度值的个数除以所有像素点的个数,即归一化 .

3.计算sumhist[i](i=1:256),sumhist[i]为前i个灰度值的分布概率hist[i]的总和.

例: sumhist[4] = hist[1] + hist[2] + hist[3] + hist[4] 

4.将sumhist乘上灰度级(通常为255),再四舍五入

5.将原图像各个灰度值转换成sumhist[i]创建出新图像.

Python图像均衡化代码

import matplotlib.pyplot as plt
import cv2
import numpy as np

imgpath = "lenna.png"


def def_equalizehist(imgpath, L=256):
    img = cv2.imread(imgpath, 1)
    cv2.imshow("ori", img)
    h, w, c = img.shape
    hist = np.zeros((256, 3))
    new_hist = np.zeros((256, 3))
    for r in range(3):
        _hist = cv2.calcHist([img], [r], None, [256], [0, 255]) #统计彩色图像每个通道的灰度值的像素点数量
        for i in range(L):
            hist[i, r] = _hist[i]
        hist[0:255, r] = hist[0:255, r] / (h * w) # 计算灰度值的像素点的概率,除以所有像素点个数,即归一化
        sum_hist = np.zeros((L, 1))
        for i in range(256):
            sum_hist[i] = sum(hist[0:i+1, r]) # 开始计算Si的一部分值,注意i每增大,Si都是对前i个灰度值的分布概率进行累加
        equal_hist = np.zeros(sum_hist.shape)
        for i in range(256):
            equal_hist[i] = int(((L - 1) - 0) * sum_hist[i] + 0.5) # Si再乘上灰度级,再四舍五入
        new_img = img.copy()
        for i in range(h):
            for j in range(w):
                new_img[i, j, r] = equal_hist[img[i, j, r]] # 新图片的创建
        #新图像的灰度值分布
        _equal_hist = cv2.calcHist([new_img], [r], None, [256], [0, 256])
        for i in range(L):
            new_hist[i, r] = _equal_hist[i]
        new_hist[0:256, r] = new_hist[0:256, r] / (h * w)
    cv2.imshow("inv", new_img)
    cv2.waitKey(0)  # 设定窗口显示时间,0表示无限
    # 显示最初的直方图
    plt.figure("原始图像直方图")
    plt.plot(hist[0:256, 0], color='b')
    plt.plot(hist[0:256, 1], color='g')
    plt.plot(hist[0:256, 2], color='r')
    plt.figure("直方均衡化直方图")
    plt.plot(new_hist[0:256, 0], color='b')
    plt.plot(new_hist[0:256, 1], color='g')
    plt.plot(new_hist[0:256, 2], color='r')
    plt.show()
    return [new_img, equal_hist]


def_equalizehist(imgpath)

参考:(26条消息) python实现直方图均衡化_熬夜大学党的博客-CSDN博客_python自适应直方图均衡化

Matlab图像均衡化代码

在matlab中可以很方便地使用其自带的histeq()函数实现图像均衡化

clc,clear,close all;
img = imread('lenna.png');
R = img(:, :, 1);
G = img(:, :, 2);
B = img(:, :, 3);
r=histeq(R);%对各个通道直方图均衡化
g=histeq(G); 
b=histeq(B);
new_img = cat(3,r,g,b);%构造多维数组
figure, 
subplot(2,2,1),imshow(img); 
title('原图像');
subplot(2,2,2),imshow(new_img); 
title('均衡化图像');
subplot(2,2,3),imhist(img); 
title('原图像直方图');
subplot(2,2,4),imhist(new_img); 
title('均衡化图像直方图');

参考:(26条消息) 彩色图像增强之直方图均衡化_拟禾的博客-CSDN博客_彩色直方图均衡

使用histeq()函数的时候还发生了个有趣的错误

我将代码保存命名为histeq.m后运行报错: 尝试将 SCRIPT histeq 作为函数执行的解决方案

于是上网寻找问题,发现是因为命名的问题,将名字改掉就好了

参考方法:(26条消息) Matlab:尝试将 SCRIPT XXX 作为函数执行的解决方案_就这样le的博客-CSDN博客_matlab尝试将script作为函数执行

使用函数这种方法很方便,但为了自身更好地了解远离,我也自己编写了程序进行图像均衡化

clc,clear,close all;
img = imread('lenna.png');
[m, n, num] = size(img);
hist = zeros(256, 1, num);
equal_hist = zeros(256,1);
new_img = zeros(m,n,num,'uint8');
for r = 1:1:num
    hist = imhist(img(:, :, r));%统计彩色图像每个通道的灰度值的像素点数量
    hist = hist/(n * m);%计算灰度值的像素点的概率,除以所有像素点个数,即归一化
    sum_hist = zeros(256,1);
    for i = 1:1:256
        for j = 1:1:i
            sum_hist(i) = sum_hist(i) + hist(j); %开始计算Si的一部分值,注意i每增大,Si都是对前i个灰度值的分布概率进行累加
        end
        equal_hist(i) = floor(255 * sum_hist(i) + 0.5); %Si再乘上灰度级,再四舍五入
    end
    for i = 1:1:m
        for j = 1:1:n
            new_img(i, j, r) = equal_hist(img(i, j, r)); %新图片的创建
        end
    end
end
new_img = im2uint8(new_img);
figure, 
subplot(2,2,1),imshow(img); 
title('原图像');
subplot(2,2,2),imshow(new_img); 
title('均衡化图像');
subplot(2,2,3),imhist(img); 
title('原图像直方图');
subplot(2,2,4),imhist(new_img); 
title('均衡化图像直方图');

结果

原图像
均衡化后图像

                   

原图像直方图分布概率
均衡化后直方图分布概率

物联沃分享整理
物联沃-IOTWORD物联网 » 图像直方图均衡方法(python和matlab实现代码)

发表评论