• python实现图像的直方图均衡化


    目录

    图像均衡化 

    批量灰度均衡化处理照片

    批量彩色均衡化照片


    图像均衡化 

    直方图均衡化是一种用于增强图像对比度的图像处理技术。它通过重新分配图像中的像素值,使得图像的像素值分布更加均匀,增强图像的对比度,从而改善图像的视觉效果。

    直方图均衡化的过程如下:

    • 灰度转换:如果图像是彩色图像,则首先需要将其转换为灰度图像。这可以通过将彩色图像的RGB通道值平均或权重化来实现,得到一个表示亮度的灰度图像。
    • 统计直方图:对于灰度图像,统计每个像素值的频数,生成原始图像的直方图。直方图表示了不同像素值的数量分布。
    • 计算累积分布函数:通过计算原始图像的累积分布函数,可以得到每个像素值的累积概率分布,即小于等于该像素值的概率。可以通过对直方图进行归一化和累加操作得到。
    • 映射像素值:根据每个像素值的累积概率分布映射出新的像素值,即将概率乘以255得到均衡化后的像素值。
    • 像素重新映射:对于原始图像中的每个像素,根据映射将其像素值替换为均衡化后的像素值。
    • 生成均衡化后的图像:根据重新映射的像素值,生成均衡化后的图像。均衡化后的图像在直方图上将有更平坦的分布,从而提高了图像的对比度。

    可以直接调用openCV的库函数实现图像的直方图均衡化

    cv2.equalizeHist(img)

    可以写一个完整的测试代码如下

    1. import matplotlib.pyplot as plt
    2. import cv2
    3. img = cv2.imread("OIP.jpg")
    4. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    5. plt.hist(img.ravel(), bins=256)
    6. plt.title('origin')
    7. plt.show() # 原始直方图
    8. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    9. plt.title('origin')
    10. plt.imshow(img)
    11. plt.show() # 原始灰度图
    12. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    13. img = cv2.equalizeHist(img)
    14. plt.hist(img.ravel(), bins=256)
    15. plt.title('systemEqualize')
    16. plt.show() # 均衡化直方图
    17. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    18. plt.imshow(img)
    19. plt.title('systemEqualize')
    20. plt.show() # 均衡化灰度图

     

    在这里我们手动实现一个图像的直方图均衡化,不调用库函数

    首先读取一张照片并将其转化为灰度图

    1. img = cv2.imread("OIP.jpg")
    2. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

    然后计算图像的直方图,并计算直方图的累积分布

    1. hist = cv2.calcHist([img], [0], None, [256], [0, 256])
    2. cdf = hist.cumsum()

    再计算像素值的累积分布概率,并根据累积分布概率映射出新的像素值,根据该映射重新分配原图像的像素值,根据插值操作可以很方便的进行一一映射,这个interp函数非常的讲究,我研究了半天还是没有看懂它的作用,直到后来看到某位大佬的解说才醍醐灌顶恍然大悟——interpret(x,xp,yp)以xp和yp构造映射函数f,返回f(x),这就让我们的像素值映射变得简单

    1. mapPixel = 255 * cdf / cdf[-1]
    2. img = numpy.interp(img.ravel(), range(256), mapPixel).reshape(img.shape)

    最后输出均衡化的图像以及均衡化的直方图,由于像素值是8位表示的,在刚才的计算过程中会使用64位进行存储,因此还需要对图像的像素值进行一下转换一下

    1. img = cv2.convertScaleAbs(img)
    2. plt.hist(img.ravel(), bins=256)
    3. plt.title('myEqualize')
    4. plt.show() # 均衡化直方图
    5. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    6. plt.imshow(img)
    7. plt.title('myEqualize')
    8. plt.show() # 均衡化灰度图

    衡化后的图像的直方图如图所示,其中左图为OpenCV库函数均衡化的效果,右图是我们手动实现均衡化的效果,可见都达到了将原图的像素值均匀分开的效果

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

     

    完整代码如下 

    1. import matplotlib.pyplot as plt
    2. import cv2
    3. import numpy
    4. img = cv2.imread("OIP.jpg")
    5. img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    6. hist = cv2.calcHist([img], [0], None, [256], [0, 256])
    7. cdf = hist.cumsum()
    8. mapPixel = 255 * cdf / cdf[-1]
    9. img = numpy.interp(img.ravel(), range(256), mapPixel).reshape(img.shape)
    10. img = cv2.convertScaleAbs(img)
    11. plt.hist(img.ravel(), bins=256)
    12. plt.title('myEqualize')
    13. plt.show() # 均衡化直方图
    14. img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    15. plt.imshow(img)
    16. plt.title('myEqualize')
    17. plt.show() # 均衡化灰度图

    批量灰度均衡化处理照片

    1. import cv2
    2. import os
    3. # 定义函数实现直方图均衡化
    4. def equalize_image(image_path):
    5. # 读取图片
    6. image = cv2.imread(image_path, cv2.IMREAD_GRAYSCALE)
    7. # 进行直方图均衡化
    8. equalized = cv2.equalizeHist(image)
    9. # 返回均衡化后的图片
    10. return equalized
    11. # 定义文件夹路径
    12. folder_path = "images"
    13. equalizePath = "equalizeImages"
    14. # 遍历文件夹中的所有图片
    15. for file_name in os.listdir(folder_path):
    16. # 判断文件是否为图片
    17. if file_name.endswith('.jpg') or file_name.endswith('.png'):
    18. # 构造图片的完整路径
    19. image_path = folder_path + '/' + file_name
    20. # 对图片进行直方图均衡化
    21. equalized_image = equalize_image(image_path)
    22. # 保存均衡化后的图片
    23. cv2.imwrite(equalizePath + '/' + file_name, equalized_image)

    批量彩色均衡化照片

    1. import cv2
    2. import os
    3. # 定义函数实现直方图均衡化
    4. def equalize_image(image_path):
    5. # 读取彩色图像
    6. image = cv2.imread(image_path, cv2.IMREAD_COLOR)
    7. # 将三个通道分别进行直方图均衡化
    8. channels = cv2.split(image)
    9. equalized_channels = []
    10. for channel in channels:
    11. equalized = cv2.equalizeHist(channel)
    12. equalized_channels.append(equalized)
    13. # 将三个均衡化后的通道合并成一张图像
    14. equalized_image = cv2.merge(equalized_channels)
    15. # 返回均衡化后的图片
    16. return equalized_image
    17. # 定义文件夹路径
    18. folder_path = "images"
    19. equalizePath = "equalizeColorfulImages"
    20. # 遍历文件夹中的所有图片
    21. for file_name in os.listdir(folder_path):
    22. # 判断文件是否为图片
    23. if file_name.endswith('.jpg') or file_name.endswith('.png'):
    24. # 构造图片的完整路径
    25. image_path = folder_path + '/' + file_name
    26. # 对图片进行直方图均衡化
    27. equalized_image = equalize_image(image_path)
    28. # 保存均衡化后的图片
    29. cv2.imwrite(equalizePath + '/' + file_name, equalized_image)
  • 相关阅读:
    windows下C++管道通信
    使用PAM保障开发运营安全
    Linux container_of() 宏定义
    数据库变更管理:Liquibase or Flyway
    【Java】并发模式
    Oracle-WeiTo基础
    pytorch 33 使用mmdeploy将mmdetection模型转换为onnx,并实现c++部署(支持动态nms)
    微信小程序实现上下手势滑动切换
    XP电源维修fleXPower电源X7-2J2J2P-120018系列详解
    Git--分布式版本控制工具
  • 原文地址:https://blog.csdn.net/weixin_62264287/article/details/133798797