针对给定的输入图像f(假设输入图像为灰度图像),根据直方图均化的表达式,利用Matlab和/或C++等编程语言完成图像直方图均化的编程实现,同时分别显示输入图像、输入图像的直方图、均化后的图像以及均化后图像的直方图,观察和分析图像显示结果。

实验2 直方图均衡化

一、导入图片

import matplotlib.pyplot as plt
import numpy as np
import cv2
path = './Images//Lab2//'

AG     = plt.imread(path+'AG.jpg')
couple = plt.imread(path+'couple.bmp')
scene1 = plt.imread(path+'scene1.jpg')
yewan  = plt.imread(path+'yewan.jpg')

plt.rcParams['figure.figsize'] = (12.0, 7.0) 
plt.subplot(2,4,1)
plt.imshow(AG, 'gray')
plt.title('AG')
plt.subplot(2,4,2)
plt.imshow(couple)
plt.title('couple')
plt.subplot(2,4,3)
plt.imshow(scene1)
plt.title('scene1')
plt.subplot(2,4,4)
plt.imshow(yewan)
plt.title('yewan')

png

二、方法类编写

# 定义直方图类
class Histogram:
    def __init__(self, image):
        self.image  = image
        self.isGray = len(image.shape)==2
        self.height = image.shape[0]
        self.width  = image.shape[1]
        self.channels_num = 1 if self.isGray else image.shape[2]

    def __myhist(self, image):
        # 计算图像直方图,image为对象图像或对象均衡化后图像
        if(len(image.shape)==2):
            hist = np.zeros([1, 256])
            max_num = np.max(image)
            min_num = np.min(image)
            for i in range(min_num, max_num+1):
                hist[0, i] = np.sum(image==i)
            assert np.sum(hist)==self.height*self.width
            return hist
        else:
            hist = np.zeros([self.channels_num, 256])
            for ch in range(self.channels_num): 
                hist[ch,:] = self.__myhist(image[:,:,ch])
        return hist

    def plotHist(self, title, HisEq=0):
        # 绘制直方图,HisEq为1可视化均衡化后图像的直方图
        if(HisEq==1):
            hist = self.__myhist(self.img_eq)
        elif(HisEq==2):
            hist = self.__myhist(self.img_from_hsv)
        elif(HisEq==3):
            hist = self.__myhist(self.img_hsv)
        else:
            hist = self.__myhist(self.image)
        for i in range(self.channels_num):
            if(self.channels_num>1):
                plt.subplot(1, self.channels_num, i+1)
                plt.title("channel"+str(i+1))
                plt.suptitle(title)
            else:
                plt.title(title)
            plt.bar(range(0,256), hist[i])

    def __HisEq(self, image):
        # 对输入image进行直方图均衡化,其中image为self.image的某个通道
        hist = self.__myhist(image)
        probs = np.cumsum(hist[0])/(self.width*self.height)
        img_map = [int(255 * probs[i]+0.5) for i in range(256)]
        img = np.zeros(image.shape, dtype=np.uint8)
        for i in range(self.height):
            for j in range(self.width):
                img[i, j] = img_map[image[i, j]]
        return img

    def HisEq(self, visualization=1, HSV=0):
        # 对self.image进行直方图均衡化,visualization=1时可视化均衡化后的图像
        # HSV=0时各个通道单独均衡化、HSV=1时将彩色图像转到HSV域, 然后使用V进行直方图均衡化。
        if self.isGray:
            if(visualization):
                plt.imshow(self.__HisEq(self.image), 'gray')
            self.img_eq = self.__HisEq(self.image)
            return self.__HisEq(self.image)
        elif(HSV):
            img_hsv = cv2.cvtColor(self.image, cv2.COLOR_RGB2HSV)
            img_hsv[:,:,2] = self.__HisEq(img_hsv[:,:,2])
            img = cv2.cvtColor(img_hsv, cv2.COLOR_HSV2RGB)
            self.img_from_hsv = img
            self.img_hsv = img_hsv
        else:
            img = np.zeros(self.image.shape, dtype=np.uint8)
            for i in range(self.channels_num):
                img[:,:,i] = self.__HisEq(self.image[:,:,i])
            self.img_eq = img

        if(visualization):
            plt.imshow(img)
        return img

三、直方图

AG_h = Histogram(AG)
couple_h = Histogram(couple)
scene1_h = Histogram(scene1)
yewan_h = Histogram(yewan)

plt.figure(figsize=(4,4))
AG_h.plotHist('AG')
plt.figure(figsize=(12,4))
couple_h.plotHist('couple')
plt.figure(figsize=(12,4))
scene1_h.plotHist('scene1')
plt.figure(figsize=(12,4))
yewan_h.plotHist('yewan')

png

png

png

png

可以看到个图像各通道的灰度值分布不均匀,且集中在很小的范围内,对比度不够,导致图像很多细节人眼辨别不出来。

四、均衡化

plt.figure(figsize=(10,10))
plt.subplot(2,2,1)
plt.imshow(AG, 'gray')
plt.title('AG')
plt.subplot(2,2,2)
AG_h.HisEq()
plt.title('HisEq-AG')
plt.subplot(2,2,3)
AG_h.plotHist('AG histogram')
plt.subplot(2,2,4)
AG_h.plotHist('HisEq-AG histogram', 1)

png

从图像上来看,图像的对比度增强—原图黑色部分更黑,白色部分更白,前景目标更为突出。

从直方图来看,原本灰度相对集中,均衡化后直方图的灰度被分散到更为广阔的灰度范围中去。

plt.figure(figsize=(14,14))
plt.subplot(1,3,1)
plt.imshow(couple)
plt.title('couple')
plt.subplot(1,3,2)
couple_h.HisEq()
plt.title('channel independent equalization')
plt.subplot(1,3,3)
couple_h.HisEq(HSV=1)
plt.title('V channel equalization')

plt.figure(figsize=(10,4))
couple_h.plotHist('image histogram')
plt.figure(figsize=(10,4))
couple_h.plotHist('channel independent equalization', 1)
plt.figure(figsize=(10,4))
couple_h.plotHist('V channel equalization---RGB', 2)
plt.figure(figsize=(10,4))
couple_h.plotHist('V channel equalization---HSV', 3)

png

png

png

png

png

可以看到单独对每一个通道进行灰度化后,每个通道的直方图都将灰度值分散开来,朝着均匀分布近似,对比度明显增强,并且原图像也不再是暗色调,各种隐藏在黑暗中的细节都能被肉眼清晰地看到。 但是由于RGB通道做了不同的变换,导致变换后的图像色调信息(H)丢失。

可以看到,通过调整HSV域中V通道(明度),这样既能保持原图像的色调和饱和度信息,又能够单独地对明度进行调整,使得图像的明暗对比度增强。

通过结果可以看到变换后的图像同样能够看到隐藏的细节,同时色调没有发生丢失。同时其HSV域的V通道的直方图也朝均匀分布近似,而H、S、R、G、B并没有这个变化倾向。

plt.figure(figsize=(14,14))
plt.subplot(1,3,1)
plt.imshow(scene1)
plt.title('scene1')
plt.subplot(1,3,2)
scene1_h.HisEq()
plt.title('channel independent equalization')
plt.subplot(1,3,3)
scene1_h.HisEq(HSV=1)
plt.title('V channel equalization')

plt.figure(figsize=(10,4))
scene1_h.plotHist('image histogram')
plt.figure(figsize=(10,4))
scene1_h.plotHist('channel independent equalization', 1)
plt.figure(figsize=(10,4))
scene1_h.plotHist('V channel equalization---RGB', 2)
plt.figure(figsize=(10,4))
scene1_h.plotHist('V channel equalization---HSV', 3)

png

png

png

png

png

plt.figure(figsize=(14,14))
plt.subplot(1,3,1)
plt.imshow(yewan)
plt.title('yewan')
plt.subplot(1,3,2)
yewan_h.HisEq()
plt.title('channel independent equalization')
plt.subplot(1,3,3)
yewan_h.HisEq(HSV=1)
plt.title('V channel equalization')

plt.figure(figsize=(10,4))
yewan_h.plotHist('image histogram')
plt.figure(figsize=(10,4))
yewan_h.plotHist('channel independent equalization', 1)
plt.figure(figsize=(10,4))
yewan_h.plotHist('V channel equalization---RGB', 2)
plt.figure(figsize=(10,4))
yewan_h.plotHist('V channel equalization---HSV', 3)

png

png

png

png

png

可以看到,所有图片在直方图均衡化后,直方图的分布范围变广,图片的对比度增强,许多隐藏在图片中的细节都呈现在肉眼前。

实验代码见: https://github.com/Yangliangzhe/Image-Processing