Python OpenCV直方图均衡化详解

作者:盼小辉丶 时间:2022-11-03 17:35:35 

前言

图像处理技术是计算机视觉项目的核心,通常是计算机视觉项目中的关键工具,可以使用它们来完成各种计算机视觉任务。在本文中,将介绍如何使用 OpenCV 函数 cv2.equalizeHist() 执行直方图均衡,并将其应用于灰度和彩色图像,cv2.equalizeHist() 函数将亮度归一化并提高图像的对比度。

灰度直方图均衡化

使用 cv2.equalizeHist() 函数来均衡给定灰度图像的对比度:

# 加载图像并转换为灰度图像
image = cv2.imread('example.png')
gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
hist = cv2.calcHist([gray_image], [0], None, [256], [0, 256])
# 直方图均衡化
gray_image_eq = cv2.equalizeHist(gray_image)
# 直方图均衡化后的图像直方图
hist_eq = cv2.calcHist([gray_image_eq], [0], None, [256], [0, 256])

为了深入了解直方图均衡,我们对原始灰度图像进行修改,为图像的每个像素添加/减去 30,并计算直方图均衡前后的直方图:

M = np.ones(gray_image.shape, dtype='uint8') * 30
# 为图像的每个像素添加 30
added_image = cv2.add(gray_image, M)
hist_added_image = cv2.calcHist([added_image], [0], None, [256], [0, 256])
# 直方图均衡化
added_image_eq = cv2.equalizeHist(gray_image_eq)
hist_eq_added_image = cv2.calcHist([added_image_eq], [0], None, [256], [0, 256])
# 为图像的每个像素减去 30
subtracted_image = cv2.subtract(gray_image, M)
hist_subtracted_image = cv2.calcHist([subtracted_image], [0], None, [256], [0, 256])
# 直方图均衡化
subtracted_image_eq = cv2.equalizeHist(subtracted_image)
hist_eq_subtracted_image = cv2.calcHist([subtracted_image_eq], [0], None, [256], [0, 256])

最后,绘制所有这些图像:

def show_img_with_matplotlib(color_img, title, pos):
   img_RGB = color_img[:, :, ::-1]
   ax = plt.subplot(3, 4, pos)
   plt.imshow(img_RGB)
   plt.title(title, fontsize=8)
   plt.axis('off')

def show_hist_with_matplotlib_gray(hist, title, pos, color):
   ax = plt.subplot(3, 4, pos)
   plt.xlabel("bins")
   plt.ylabel("number of pixels")
   plt.xlim([0, 256])
   plt.plot(hist, color=color)
# 可视化
show_img_with_matplotlib(cv2.cvtColor(gray_image, cv2.COLOR_GRAY2BGR), "gray", 1)
show_hist_with_matplotlib_gray(hist, "grayscale histogram", 2, 'm')
show_img_with_matplotlib(cv2.cvtColor(added_image, cv2.COLOR_GRAY2BGR), "gray lighter", 5)
show_hist_with_matplotlib_gray(hist_added_image, "grayscale histogram", 6, 'm')
show_img_with_matplotlib(cv2.cvtColor(subtracted_image, cv2.COLOR_GRAY2BGR), "gray darker", 9)
show_hist_with_matplotlib_gray(hist_subtracted_image, "grayscale histogram", 10, 'm')
# 其他图像的可视化方法类似,不再赘述
# ...

程序运行的输出如下图所示:

Python OpenCV直方图均衡化详解

在上图中,我们可以看到三个均衡化后的图像非常相似,这也反映在均衡化后的直方图中,这是因为直方图均衡化倾向于标准化图像的亮度,同时增加对比度。

颜色直方图均衡化

使用相同的方法,我们可以在彩色图像中执行直方图均衡,将直方图均衡应用于 BGR 图像的每个通道(虽然这不是彩色图像直方图均衡的最佳方法),创建 equalize_hist_color() 函数,使用 cv2.split() 分割 BGR 图像并将 cv2.equalizeHist() 函数应用于每个通道,最后,使用 cv2.merge() 合并结果通道:

def equalize_hist_color(img):
   # 使用 cv2.split() 分割 BGR 图像
   channels = cv2.split(img)
   eq_channels = []
   # 将 cv2.equalizeHist() 函数应用于每个通道
   for ch in channels:
       eq_channels.append(cv2.equalizeHist(ch))
   # 使用 cv2.merge() 合并所有结果通道
   eq_image = cv2.merge(eq_channels)
   return eq_image

接下来,将此函数应用于三个不同的图像:原始 BGR 图像、将原始图像的每个像素值添加 10、将原始图像的每个像素值减去 10,并计算直方图均衡前后的直方图:

# 加载图像
image = cv2.imread('example.png')
# 计算直方图均衡前后的直方图
hist_color = hist_color_img(image)
image_eq = equalize_hist_color(image)
hist_image_eq = hist_color_img(image_eq)

M = np.ones(image.shape, dtype="uint8") * 10
# 为图像的每个像素添加 10
added_image = cv2.add(image, M)
# 直方图均衡前后的直方图
hist_color_added_image = hist_color_img(added_image)
added_image_eq = equalize_hist_color(added_image)
hist_added_image_eq = hist_color_img(added_image_eq)
# 为图像的每个像素减去 10
subtracted_image = cv2.subtract(image, M)
# 直方图均衡前后的直方图
hist_color_subtracted_image = hist_color_img(subtracted_image)
subtracted_image_eq = equalize_hist_color(subtracted_image)
hist_subtracted_image_eq = hist_color_img(subtracted_image_eq)

最后,绘制所有这些图像:

def show_img_with_matplotlib(color_img, title, pos):
   img_RGB = color_img[:, :, ::-1]
   ax = plt.subplot(3, 4, pos)
   plt.imshow(img_RGB)
   plt.title(title, fontsize=8)
   plt.axis('off')

def show_hist_with_matplotlib_rgb(hist, title, pos, color):
   ax = plt.subplot(3, 4, pos)
   plt.xlabel("bins")
   plt.ylabel("number of pixels")
   plt.xlim([0, 256])
   for (h, c) in zip(hist, color):
       plt.plot(h, color=c)
# 可视化
show_img_with_matplotlib(image, "image", 1)
show_hist_with_matplotlib_rgb(hist_color, "color histogram", 2, ['b', 'g', 'r'])
show_img_with_matplotlib(added_image, "image lighter", 5)
show_hist_with_matplotlib_rgb(hist_color_added_image, "color histogram", 6, ['b', 'g', 'r'])
show_img_with_matplotlib(subtracted_image, "image darker", 9)
show_hist_with_matplotlib_rgb(hist_color_subtracted_image, "color histogram", 10, ['b', 'g', 'r'])
# 其他图像的可视化方法类似,不再赘述
# ...

Python OpenCV直方图均衡化详解

将直方图均衡化应用于 BGR 图像的每个通道并不是颜色直方图均衡化的好方法,这是由于 BGR 色彩空间的加性特性导致彩色图像的颜色变化很大。由于我们独立地改变三个通道中的亮度和对比度,因此在合并均衡通道时,这可能会导致图像中出现新的色调,正如上图所看到的那样。

一种颜色直方图均衡化更好的方法是将 BGR 图像转换为包含亮度/强度通道的色彩空间( YuvLabHSVHSL )。然后,只在亮度通道上应用直方图均衡,最后合并通道并将它们转换回 BGR 颜色空间,以 HSV 空间为例,创建 equalize_hist_color_hsv() 函数实现上述颜色直方图归一化方法:

def equalize_hist_color_hsv(img):
   H, S, V = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))
   eq_V = cv2.equalizeHist(V)
   eq_image = cv2.cvtColor(cv2.merge([H, S, eq_V]), cv2.COLOR_HSV2BGR)
   return eq_image

接下来,将此函数应用于三个不同的图像:原始 BGR 图像、将原始图像的每个像素值添加 10、将原始图像的每个像素值减去 10,并计算直方图均衡前后的直方图:

hist_color = hist_color_img(image)
# 计算直方图均衡前后的直方图
image_eq = equalize_hist_color_hsv(image)
hist_image_eq = hist_color_img(image_eq)

M = np.ones(image.shape, dtype="uint8") * 10
# 为图像的每个像素添加 10
added_image = cv2.add(image, M)
hist_color_added_image = hist_color_img(added_image)
# 直方图均衡前后的直方图
added_image_eq = equalize_hist_color_hsv(added_image)
hist_added_image_eq = hist_color_img(added_image_eq)
# 为图像的每个像素减去 10
subtracted_image = cv2.subtract(image, M)
hist_color_subtracted_image = hist_color_img(subtracted_image)
# 直方图均衡前后的直方图
subtracted_image_eq = equalize_hist_color_hsv(subtracted_image)
hist_subtracted_image_eq = hist_color_img(subtracted_image_eq)

最后,绘制所有这些图像:

# show_img_with_matplotlib() 和 show_hist_with_matplotlib_rgb() 函数与上一示例相同
show_img_with_matplotlib(image, "image", 1)
show_hist_with_matplotlib_rgb(hist_color, "color histogram", 2, ['b', 'g', 'r'])
show_img_with_matplotlib(added_image, "image lighter", 5)
show_hist_with_matplotlib_rgb(hist_color_added_image, "color histogram", 6, ['b', 'g', 'r'])
# 其他图像的可视化方法类似,不再赘述
# ...

Python OpenCV直方图均衡化详解

由上图可以看出,仅均衡 HSV 图像的 V 通道得到的结果比均衡 BGR 图像的所有通道的效果要好很多,也可以将这种方法用于其他包含亮度/强度通道的色彩空间( YuvLabHSL )。

来源:https://juejin.cn/post/7060674333349249031

标签:Python,OpenCV,直方图,均衡化
0
投稿

猜你喜欢

  • ASP利用 xmlhttp 分块上传文件

    2007-11-01 22:55:00
  • Javascript 两个窗体之间传值实现代码

    2024-04-22 22:31:11
  • Oracle 中文字段进行排序的sql语句

    2024-01-22 13:26:43
  • python使用opencv在Windows下调用摄像头实现解析

    2021-01-08 04:13:01
  • Python之列表推导式最全汇总(中篇)

    2022-05-25 20:56:59
  • PHP原型模式Prototype Pattern的使用介绍

    2023-05-25 01:21:04
  • 使用pkg打包Node.js应用的方法步骤

    2024-05-13 09:58:30
  • tensorflow求导和梯度计算实例

    2023-08-09 14:07:38
  • Zend Framework教程之资源(Resources)用法实例详解

    2023-11-06 02:49:50
  • Python Selenium XPath根据文本内容查找元素的方法

    2022-02-18 12:55:16
  • SQLServer 2008中通过DBCC OPENTRAN和会话查询事务

    2024-01-13 15:35:55
  • Microsoft JET Database Engine 错误 '80040e21' 所有记录中均未找到搜索关键字

    2009-08-30 13:07:00
  • 一篇文章带你搞定 springsecurity基于数据库的认证(springsecurity整合mybatis)

    2024-01-20 23:15:34
  • 创建动态MSSQL数据库表

    2024-01-19 03:04:08
  • python中split(), os.path.split()和os.path.splitext()的用法

    2022-03-23 09:06:40
  • GO语言ini配置文件的读取的操作

    2024-04-23 09:38:36
  • Python urllib库的使用指南详解

    2021-07-08 20:50:57
  • python3第三方爬虫库BeautifulSoup4安装教程

    2023-05-10 21:11:57
  • SQL游标原理和使用方法

    2008-12-22 10:50:00
  • Python接口自动化浅析数据驱动原理

    2022-02-22 21:52:01
  • asp之家 网络编程 m.aspxhome.com