灰度图像和彩色图像的直方图均衡化(python实现)

  • 原理描述
    • 直方图均衡化
    • 直方图均衡化算法
    • 彩色图像
    • HSI模型<->RGB模型
  • 代码
    • 灰度图像直方图均衡化
    • 彩色图像直方图均衡化(内含hsi模型和rgb模型互换)
  • 实验结果
    • 问题
    • 感想

原理描述

直方图均衡化

直方图是图像中像素强度分布的图形表达方式。它统计了每一个强度值所具有的像素个数。直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法。是图像处理领域中利用图像直方图对对比度进行调整的方法。均衡化指的是把一个分布(给定的直方图)映射到另一个分布(一个更宽更统一的强度值分布),所以强度值分布会在整个范围内展开。映射函数应该是一个累积分布函数。直方图均衡化是通过调整图像的灰阶分布,使得在0~255灰阶上的分布更加均衡,提高了图像的对比度,达到改善图像主观视觉效果的目的。对比度较低的图像适合使用直方图均衡化方法来增强图像细节。这种方法通常用来增加许多图像的全局对比度,尤其是当图像的有用数据的对比度相当接近的时候。通过这种方法,亮度可以更好地在直方图上分布。这样就可以用于增强局部的对比度而不影响整体的对比度,直方图均衡化通过有效地扩展常用的亮度来实现这种功能。这种方法对于背景和前景都太亮或者太暗的图像非常有用,这种方法尤其是可以带来X光图像中更好的骨骼结构显示以及曝光过度或者曝光不足照片中更好的细节。这种方法的一个主要优势是它是一个相当直观的技术并且是可逆操作,如果已知均衡化函数,那么就可以恢复原始的直方图,并且计算量也不大。这种方法的一个缺点是它对处理的数据不加选择,它可能会增加背景噪声的对比度并且降低有用信号的对比度。

直方图均衡化算法

  1. 统计原始图像各灰度级的像素数目ni,0≤i<L, L是图像中所有的灰度数(通常为256);
  2. 图像中灰度为i的像素的出现概率是:px(i)=p(x=i)=ni/n,n是图像中所有的像素数,px(i)实际上是像素值为i的图像的直方图,归一化到[0, 1];
  3. px的累积分布函数,是图像的累计归一化直方图:
  4. 直方图均衡化计算公式, cdfmin为累积分布函数最小值,M和N分别代表了图像的长宽像素个数,而L则是灰度级数(如图像为8位深度,则灰度级别共有2^8=256级数,这也是最常见的灰度级数),v为原始图像中为v的像素值:
  5. 增加了支持甘特图的mermaid语法[^1] 功能;

彩色图像

彩色图像直方图均衡化:上面描述了灰度图像上使用直方图均衡化的方法,但是通过将这种方法分别用于图像RGB颜色值的红色、绿色和蓝色分量,从而也可以对彩色图像进行处理。实际上,对彩色分量rgb分别做均衡化,会产生奇异的点,图像不和谐。一般采用的是用yuv空间进行亮度的均衡即可。本实验我们采用的是将图像由RGB色彩空间到HSI的变换,然后在亮度通道上进行直方图均衡化;均衡化原理同灰度图像。

HSI模型<->RGB模型

HSI颜色模型是一个满足计算机数字化颜色管理需要的高度抽象模拟的数学模型。HSI模型是从人的视觉系统出发,直接使用颜色三要素–色调(Hue)、饱和度(Saturation)和亮度(Intensity,有时也翻译作密度或灰度)来描述颜色。
RGB向HSI模型的转换是由一个基于笛卡尔直角坐标系的单位立方体向基于圆柱极坐标的双锥体的转换。基本要求是将RGB中的亮度因素分离,通常将色调和饱和度统称为色度,用来表示颜色的类别与深浅程度。在图中圆锥中间的横截面圆就是色度圆,而圆锥向上或向下延伸的便是亮度分量的表示。

从RGB空间到HSI空间的转换有多种方法,这里仅说明最为经典的几何推导法。RGB转化成HSI的公式为:

HSI转化成RGB的公式为:

代码

灰度图像直方图均衡化

import cv2
import numpy as np
import matplotlib.pyplot as plt
import collections# 计算灰度图的直方图
def draw_histogram(grayscale):gray_key = []gray_count = []gray_result = []histogram_gray = list(grayscale.ravel())  # 将多维数组转换成一维数组gray = dict(collections.Counter(histogram_gray))  # 统计图像中每个灰度级出现的次数gray = sorted(gray.items(), key=lambda item: item[0])  # 根据灰度级大小排序for element in gray:key = list(element)[0]count = list(element)[1]gray_key.append(key)gray_count.append(count)for i in range(0, 256):if i in gray_key:num = gray_key.index(i)gray_result.append(gray_count[num])else:gray_result.append(0)gray_result = np.array(gray_result)return gray_resultdef histogram_equalization(histogram_e, lut_e, image_e):sum_temp = 0cf = []for i in histogram_e:sum_temp += icf.append(sum_temp)for i, v in enumerate(lut_e):lut_e[i] = int(255.0 * (cf[i] / sum_temp) + 0.5)equalization_result = lut_e[image_e]return equalization_resultx = []
for i in range(0, 256):  # 横坐标x.append(i)image = cv2.imread(r'.\Images\grey.png', cv2.COLOR_BGR2GRAY)  # 读取图像
histogram = draw_histogram(image)  # 直方图转化
plt.bar(x, histogram)  # 绘制原图直方图
plt.savefig('./equalization_gray/before_histogram.png')
plt.show()lut = np.zeros(256, dtype=image.dtype)  # 创建空的查找表,返回image类型的用0填充的数组;
result = histogram_equalization(histogram, lut, image)  # 均衡化处理
cv2.imwrite('./equalization_gray/his_grey.png', result)  # 保存均衡化后图片image_equ = cv2.imread(r'.\equalization_gray\his_grey.png', cv2.COLOR_BGR2GRAY)  # 读取图像
histogram_equ = draw_histogram(image_equ)  # 直方图转化
plt.bar(x, histogram_equ)  # 绘制处理后图像直方图
plt.savefig('./equalization_gray/after_histogram.png')
plt.show()plt.plot(x, lut)  # 绘制灰度级变换曲线图
plt.savefig('./equalization_gray/Grayscale_transformation_curve.png')
plt.show()cv2.imshow('former', image)
cv2.imshow("histogram_equalization", result)
cv2.waitKey(0)
cv2.destroyAllWindows()

彩色图像直方图均衡化(内含hsi模型和rgb模型互换)

import cv2
import numpy as np
import matplotlib.pyplot as plt
import collectionsdef rgb_hsi(rgb_image):# 保存原始图像的行列数rows = int(rgb_image.shape[0])cols = int(rgb_image.shape[1])# 图像复制hsi_image = rgb_image.copy()# 通道拆分b = rgb_image[:, :, 0]g = rgb_image[:, :, 1]r = rgb_image[:, :, 2]# 归一化到[0,1]b = b / 255.0g = g / 255.0r = r / 255.0for i in range(rows):for j in range(cols):num = 0.5 * ((r[i, j]-g[i, j])+(r[i, j]-b[i, j]))den = np.sqrt((r[i, j]-g[i, j])**2+(r[i, j]-b[i, j])*(g[i, j]-b[i, j]))if den == 0:hsi_h = 0else:theta = float(np.arccos(num / den))if b[i, j] <= g[i, j]:hsi_h = thetaelse:hsi_h = 2*np.pi - thetamin_RGB = min(min(b[i, j], g[i, j]), r[i, j])sum = b[i, j]+g[i, j]+r[i, j]if sum == 0:hsi_s = 0else:hsi_s = 1 - 3*min_RGB/sumhsi_h = hsi_h/(2*np.pi)hsi_i = sum/3.0# 输出HSI图像,扩充到255以方便显示,一般H分量在[0,2pi]之间,S和I在[0,1]之间hsi_image[i, j, 0] = hsi_h*255hsi_image[i, j, 1] = hsi_s*255hsi_image[i, j, 2] = hsi_i*255return hsi_imagedef hsi_rgb(hsi_image):# 保存原始图像的行列数rows = np.shape(hsi_image)[0]cols = np.shape(hsi_image)[1]# 对原始图像进行复制rgb_image = hsi_image.copy()# 对图像进行通道拆分hsi_h = hsi_image[:, :, 0]hsi_s = hsi_image[:, :, 1]hsi_i = hsi_image[:, :, 2]# 把通道归一化到[0,1]hsi_h = hsi_h / 255.0hsi_s = hsi_s / 255.0hsi_i = hsi_i / 255.0B, G, R = hsi_h, hsi_s, hsi_ifor i in range(rows):for j in range(cols):hsi_h[i, j] *= 360if 0 <= hsi_h[i, j] < 120:B = hsi_i[i, j] * (1 - hsi_s[i, j])R = hsi_i[i, j] * (1 + (hsi_s[i, j] * np.cos(hsi_h[i, j] * np.pi / 180)) / np.cos((60 - hsi_h[i, j]) * np.pi / 180))G = 3 * hsi_i[i, j] - (R + B)elif 120 <= hsi_h[i, j] < 240:hsi_h[i, j] = hsi_h[i, j] - 120R = hsi_i[i, j] * (1 - hsi_s[i, j])G = hsi_i[i, j] * (1 + (hsi_s[i, j] * np.cos(hsi_h[i, j] * np.pi / 180)) / np.cos((60 - hsi_h[i, j]) * np.pi / 180))B = 3 * hsi_i[i, j] - (R + G)elif 240 <= hsi_h[i, j] <= 300:hsi_h[i, j] = hsi_h[i, j] - 240G = hsi_i[i, j] * (1 - hsi_s[i, j])B = hsi_i[i, j] * (1 + (hsi_s[i, j] * np.cos(hsi_h[i, j] * np.pi / 180)) / np.cos((60 - hsi_h[i, j]) * np.pi / 180))R = 3 * hsi_i[i, j] - (G + B)rgb_image[i, j, 0] = B * 255rgb_image[i, j, 1] = G * 255rgb_image[i, j, 2] = R * 255return rgb_image# 计算灰度图的直方图
def draw_histogram(grayscale):# 对图像进行通道拆分hsi_i = grayscale[:, :, 2]color_key = []color_count = []color_result = []histogram_color = list(hsi_i.ravel())  # 将多维数组转换成一维数组color = dict(collections.Counter(histogram_color))  # 统计图像中每个亮度级出现的次数color = sorted(color.items(), key=lambda item: item[0])  # 根据亮度级大小排序for element in color:key = list(element)[0]count = list(element)[1]color_key.append(key)color_count.append(count)for i in range(0, 256):if i in color_key:num = color_key.index(i)color_result.append(color_count[num])else:color_result.append(0)color_result = np.array(color_result)return color_resultdef histogram_equalization(histogram_e, lut_e, image_e):sum_temp = 0cf = []for i in histogram_e:sum_temp += icf.append(sum_temp)for i, v in enumerate(lut_e):lut_e[i] = int(255.0 * (cf[i] / sum_temp) + 0.5)equalization_result = lut_e[image_e]return equalization_resultx = []
for i in range(0, 256):  # 横坐标x.append(i)# 原图及其直方图
rgb_image = cv2.imread(".\Images\color.jpg")
cv2.imshow('rgb', rgb_image)
histogram = draw_histogram(rgb_image)
plt.bar(x, histogram)  # 绘制原图直方图
plt.savefig('./equalization_color/before_histogram.png')
plt.show()# rgb转hsi
hsi_image = rgb_hsi(rgb_image)
cv2.imshow('hsi_image', hsi_image)
cv2.imwrite('./equalization_color/hsi_result.png', hsi_image)# hsi在亮度分量上均衡化
histogram_1 = draw_histogram(hsi_image)
lut = np.zeros(256, dtype=hsi_image.dtype)  # 创建空的查找表
result = histogram_equalization(histogram_1, lut, hsi_image)  # 均衡化处理
cv2.imshow('his_color_image', result)
cv2.imwrite('./equalization_color/his_color.png', result)  # 保存均衡化后图片# hsi转rgb
image_equ = cv2.imread(r'.\equalization_color\his_color.png')  # 读取图像
rgb_result = hsi_rgb(image_equ)
cv2.imshow('rgb_image', rgb_result)
cv2.imwrite('./equalization_color/gbr_result.png', rgb_result)rgb = cv2.imread(".\equalization_color\gbr_result.png")
histogram_2 = draw_histogram(rgb)
plt.bar(x, histogram_2)
plt.savefig('./equalization_color/after_histogram.png')
plt.show()plt.plot(x, lut)  # 绘制灰度级变换曲线图
plt.savefig('./equalization_color/Grayscale_transformation_curve.png')
plt.show()cv2.waitKey(0)
cv2.destroyAllWindows()

实验结果

描述:原灰度图像通过opencv读取到程序中,统计各个灰度级的比重后,按照直方图均衡化的步骤依次计算,得出映射关系,画出直方图及灰度变换曲线图。
原灰度图像及其直方图

均衡化结果及其直方图

描述:原彩色图像通过opencv读取到程序中,先转换成HSI彩色模型,对I分量即亮度通道进行直方图均衡化,再将均衡化后的图像转换成RGB彩色模型,得出映射关系,画出直方图及灰度变换曲线图。
原彩色图像及其直方图

rgb模型转hsi模型图像及其均衡化结果

hsi均衡化结果转回rgb图像及其直方图

问题

问题:opencv无法安装
解决方法:python3.8版本与opencv不兼容,改用python3.7即可
问题:重写cv2.split()拆分通道函数
解决方法:了解了cv2.imread()函数读取图像后返回值的格式, hsi_h = hsi_image[:, :, 0],hsi_s = hsi_image[:, :, 1],hsi_i = hsi_image[:, :, 2]直接拆分通道。

感想

通过这次实验,我了解到数字图像处理的一些方法应用,也让我对于直方图均衡化以及HSI彩色模型和RGB彩色模型有了更加深刻的理解和认知,数字图像处理是一门十分有用也十分有趣的学科,值得我们去挖掘和探索。

灰度图像和彩色图像的直方图均衡化(python实现)相关推荐

  1. matlab实现彩色图像的直方图均衡化

    本篇用于记录用matlab实现彩色图像的直方图均衡化算法,并与matlab自带的直方图均衡化函数histeq做对比. 直方图原理可以参考下面的博客文章:直方图均衡化 原理.流程.公式推导及matlab ...

  2. 彩色图像的直方图均衡化

    彩色图像的直方图均衡化 1.彩色图像的直方图均衡化 这里我采用的方法是直接将彩色图像的 R . G . B 分量做直方图均衡化然后再将三个分量合并起来. 2.实现代码 (1)灰度图的直方图均衡化,曾经 ...

  3. python批量直方图均衡化_直方图均衡化-Python实现

    需要均衡的图像 将下面的图像进行直方图均衡 1 3 9 9 8 2 1 3 7 3 3 6 0 6 4 6 8 2 0 5 2 9 2 6 0 均衡化计算过程 使用python进行直方图均衡化: # ...

  4. 计算机视觉——图像去噪及直方图均衡化(图像增强)

    目录 系列文章目录 一.实验内容与方法 二.图像的加噪 1.高斯噪声 2.椒盐噪声 三.图像的去/降噪 1.均值滤波 2.中值滤波 四.直方图与均衡化 1.直方图 2.直方图均衡化 五.灰度图均衡化 ...

  5. opencv python 实现灰度图像和彩色图像直方图全局均衡化和自适应均衡化

    首先进行简单的灰度图像的全局均衡化和自适应均衡化 import cv2 as cv import numpy as npimg = cv.imread('cun.jpg',0)# 全局直方图均衡化 i ...

  6. python图像直方图与直方图均衡化

    图像直方图以及灰度与彩色图像的直方图均衡化 图像直方图: 图像的直方图用来表征该图像像素值的分布情况.用一定数目的小区间(bin)来指定表征像素值的范围,每个小区间会得到落入该小区间表示范围的像素数目 ...

  7. python opencv 直方图均衡_深入理解OpenCV+Python直方图均衡化

    原标题:深入理解OpenCV+Python直方图均衡化 正文 直方图均衡化是图像处理领域中利用图像直方图对对比度进行调整的方法. 基本思想:把原始图的直方图变换为均匀分 布的形式,这样就增加了像素灰度 ...

  8. python+opencv直方图均衡化

    前言 直方图均衡化的三种情况,分别是: - 灰度图像直方图均衡化 - 彩色图像直方图均衡化 - YUV 直方图均衡化 插入原图: 灰度图像直方图均衡化 对直方图均衡化主要使用opencv提供的一个eq ...

  9. MATLAB-真彩色图像直方图均衡化及分别在RGB与HSI坐标系进行处理

    目录 灰度直方图 什么是灰度直方图? 灰度直方图的性质 直方图均衡化处理灰度图像 均衡化步骤 代码 代码分析 直方图均衡化处理真彩色图像 代码 代码分析 灰度直方图 什么是灰度直方图? (已知晓的请直 ...

  10. OpenCV:利用python来实现图像的直方图均衡化

    文章目录 1.直方图 2.直方图均衡化 3.源代码实现直方图均衡化 1.直方图 直方图: (1) 图像中不同像素等级出现的次数 (2) 图像中具有不同等级的像素关于总像素数目的比值. 我们使用cv2. ...

最新文章

  1. uNetXST:将多个车载摄像头转换为鸟瞰图语义分割图像
  2. 你们网购遇到过这种店铺吗?我吓得第二天就退货了
  3. 如何在面试结束后反问面试技术官?
  4. 上传文件到某文件夹时,提示...路径访问被拒绝
  5. 背景图片自适应大小(css3)
  6. 485通讯线是几芯的_RS232/485串口通讯基础知识
  7. c语言运算优先级口诀简单,C语言运算符优先级和口诀
  8. Markdown中LaTeX公式编号
  9. 谷歌广告联盟(Google Adsense)通过网站获利功能在线创收
  10. 爱奇艺SOAR探索与实践
  11. windows10家庭版修改中文用户名完美解决
  12. jQuery酷炫的文字动画效果代码
  13. 横河dcs系统配有服务器吗,横河DCS常见问题的解答 转贴
  14. MATLAB求解非线性方程组的五种方法
  15. 燃动金秋,Stibo Systems(思迪博) 软件受邀参加2021中国服贸会
  16. Highcharts Gantt JS 现代 Web 开发的甘特图
  17. 公司地址跨区变更流程
  18. Java基础匿名内部类
  19. FFmpeg滤镜:制作图片视频流
  20. ABB DSD系列DSDP170、DSDX404、DSDX452、DSDP140B、DSDO115A、DSDX453、DSDP150、DSDP140A

热门文章

  1. 易飞erp系统服务器怎么启动,如何使用易飞ERP系统
  2. 计算机组成原理期末知识点复习及考点总结
  3. [RK356x] [Firefly-Ubuntu] 1min教你在Ubuntu系统安装GCC开发工具
  4. UDS 0x22服务 DID增加流程
  5. CSDN去除图片水印
  6. jquery closest()的用法
  7. 基于宝塔面板把网站和数据库文件备份到又拍云存储空间图文教程
  8. $body.on(‘click‘,‘button‘,function() {中.on在这里是什么意思的
  9. 详解PON基础知识:OLT、ONU、ONT和ODN
  10. 搞笑--网络小说-紫川 高考题-(附答案)