目录
直方图均衡化是一种用于增强图像对比度的图像处理技术。它通过重新分配图像中的像素值,使得图像的像素值分布更加均匀,增强图像的对比度,从而改善图像的视觉效果。
直方图均衡化的过程如下:
可以直接调用openCV的库函数实现图像的直方图均衡化
cv2.equalizeHist(img)


可以写一个完整的测试代码如下
- import matplotlib.pyplot as plt
- import cv2
-
- img = cv2.imread("OIP.jpg")
- img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- plt.hist(img.ravel(), bins=256)
- plt.title('origin')
- plt.show() # 原始直方图
- img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- plt.title('origin')
- plt.imshow(img)
- plt.show() # 原始灰度图
-
- img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- img = cv2.equalizeHist(img)
- plt.hist(img.ravel(), bins=256)
- plt.title('systemEqualize')
- plt.show() # 均衡化直方图
- img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- plt.imshow(img)
- plt.title('systemEqualize')
- plt.show() # 均衡化灰度图


在这里我们手动实现一个图像的直方图均衡化,不调用库函数
首先读取一张照片并将其转化为灰度图
- img = cv2.imread("OIP.jpg")
- img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
然后计算图像的直方图,并计算直方图的累积分布
- hist = cv2.calcHist([img], [0], None, [256], [0, 256])
- cdf = hist.cumsum()
再计算像素值的累积分布概率,并根据累积分布概率映射出新的像素值,根据该映射重新分配原图像的像素值,根据插值操作可以很方便的进行一一映射,这个interp函数非常的讲究,我研究了半天还是没有看懂它的作用,直到后来看到某位大佬的解说才醍醐灌顶恍然大悟——interpret(x,xp,yp)以xp和yp构造映射函数f,返回f(x),这就让我们的像素值映射变得简单
- mapPixel = 255 * cdf / cdf[-1]
- img = numpy.interp(img.ravel(), range(256), mapPixel).reshape(img.shape)
最后输出均衡化的图像以及均衡化的直方图,由于像素值是8位表示的,在刚才的计算过程中会使用64位进行存储,因此还需要对图像的像素值进行一下转换一下
- img = cv2.convertScaleAbs(img)
- plt.hist(img.ravel(), bins=256)
- plt.title('myEqualize')
- plt.show() # 均衡化直方图
- img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- plt.imshow(img)
- plt.title('myEqualize')
- plt.show() # 均衡化灰度图
衡化后的图像的直方图如图所示,其中左图为OpenCV库函数均衡化的效果,右图是我们手动实现均衡化的效果,可见都达到了将原图的像素值均匀分开的效果


均衡化后的图像如图所示,其中左图为OpenCV库函数均衡化的效果,右图是我们手动实现均衡化的效果,可知二者效果基本相同,与原图相比,均衡化后的图像对比度提高了,其中云层增加了更多的细节,看起来更清晰了一些

完整代码如下
- import matplotlib.pyplot as plt
- import cv2
- import numpy
-
- img = cv2.imread("OIP.jpg")
- img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
- hist = cv2.calcHist([img], [0], None, [256], [0, 256])
- cdf = hist.cumsum()
- mapPixel = 255 * cdf / cdf[-1]
- img = numpy.interp(img.ravel(), range(256), mapPixel).reshape(img.shape)
- img = cv2.convertScaleAbs(img)
- plt.hist(img.ravel(), bins=256)
- plt.title('myEqualize')
- plt.show() # 均衡化直方图
- img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
- plt.imshow(img)
- plt.title('myEqualize')
- plt.show() # 均衡化灰度图
- import cv2
- import os
-
-
- # 定义函数实现直方图均衡化
- def equalize_image(image_path):
- # 读取图片
- image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
- # 进行直方图均衡化
- equalized = cv2.equalizeHist(image)
- # 返回均衡化后的图片
- return equalized
-
-
- # 定义文件夹路径
- folder_path = "images"
- equalizePath = "equalizeImages"
- # 遍历文件夹中的所有图片
- for file_name in os.listdir(folder_path):
- # 判断文件是否为图片
- if file_name.endswith('.jpg') or file_name.endswith('.png'):
- # 构造图片的完整路径
- image_path = folder_path + '/' + file_name
- # 对图片进行直方图均衡化
- equalized_image = equalize_image(image_path)
- # 保存均衡化后的图片
- cv2.imwrite(equalizePath + '/' + file_name, equalized_image)
- import cv2
- import os
-
-
- # 定义函数实现直方图均衡化
- def equalize_image(image_path):
- # 读取彩色图像
- image = cv2.imread(image_path, cv2.IMREAD_COLOR)
- # 将三个通道分别进行直方图均衡化
- channels = cv2.split(image)
- equalized_channels = []
- for channel in channels:
- equalized = cv2.equalizeHist(channel)
- equalized_channels.append(equalized)
- # 将三个均衡化后的通道合并成一张图像
- equalized_image = cv2.merge(equalized_channels)
- # 返回均衡化后的图片
- return equalized_image
-
-
- # 定义文件夹路径
- folder_path = "images"
- equalizePath = "equalizeColorfulImages"
- # 遍历文件夹中的所有图片
- for file_name in os.listdir(folder_path):
- # 判断文件是否为图片
- if file_name.endswith('.jpg') or file_name.endswith('.png'):
- # 构造图片的完整路径
- image_path = folder_path + '/' + file_name
- # 对图片进行直方图均衡化
- equalized_image = equalize_image(image_path)
- # 保存均衡化后的图片
- cv2.imwrite(equalizePath + '/' + file_name, equalized_image)