直方图均衡化和自适应直方图均衡化
前言:Hello大家好,我是Dream。 均衡化是数字图像处理中常用的一种技术,用于增强图像的视觉效果和对比度。,今天我们将实现对同一张图像的直方图均衡化和自适应直方图均衡化处理,学习一下两者的的基本原理和实现过程,一起来看看吧~
一、直方图均衡化
直方图均衡化(Histogram Equalization)是一种图像处理技术,通过重新分配图像灰度级别来增强图像的对比度和视觉效果。它基于整个图像的灰度直方图来调整像素的灰度值分布。通过增加较暗区域的亮度和减少较亮区域的亮度,直方图均衡化可以使图像的灰度级别分布更均匀,从而增强图像的细节和对比度。
1.得到灰度图
通过三同道的彩色图生成单通道的灰度图
首先,我们使用PIL库中的Image.open()函数读取彩色图像,并将其转换为数组。然后,我们获取图像的高度和宽度,并创建一个与原始图像大小相同、数据类型为uint8的全黑数组gray_img,用于保存灰度图像。
接着,我们遍历每个像素,将三个通道的值求平均,并将结果保存到灰度图像中。由于RGB图像的三个通道具有相同的权重,因此将三个通道的值求平均可以得到一个比较准确的灰度值。
然后,我们将灰度图像转换为PIL图像对象,并使用Matplotlib库中的plt.imshow()函数显示彩色图像和灰度图像。最后,我们使用PIL库中的Image.save()函数将灰度图像保存为文件。
import numpy as np
import cv2
from PIL import Image
import matplotlib.pyplot as plt# 读取彩色图像
img = Image.open('image.jpg')# 将图像转换为数组
img_arr = np.array(img)# 获取图像的高度和宽度
h, w, _ = img_arr.shape# 创建一个新的数组,用于保存灰度图像
gray_img = np.zeros((h, w), dtype=np.uint8)# 遍历每个像素,将三个通道的值求平均,并保存到灰度图像中
for i in range(h):for j in range(w):gray_img[i, j] = int(np.mean(img_arr[i, j]))# 将灰度图像转换为PIL图像对象
gray_pil_img = Image.fromarray(gray_img)
plt.imshow(img)
plt.title('imge')
plt.axis('off')
plt.show()
plt.imshow(gray_pil_img, cmap='gray')
plt.title('gray_pil_imge')
plt.axis('off')
plt.show()
# 保存灰度图像
gray_pil_img.save('gray_image.jpg')


2. 直方图统计
使用PIL库中的Image.open()函数读取灰度图像,并使用convert('L')方法将图像转换为灰度模式。然后,我们获取图像的宽度和高度,并创建一个长度为256的全0列表hist,用于保存直方图统计结果。
接着,遍历每个像素,获取其灰度值,并将对应的直方图计数器加1。最后,我们输出直方图统计结果,即每个灰度值出现的像素数。
# 读取灰度图像
gray_img = Image.open('gray_image.jpg').convert('L')
width, height = gray_img.size# 统计直方图
hist = [0] * 256
for y in range(height):for x in range(width):pixel = gray_img.getpixel((x, y))hist[pixel] += 1
print(hist)
# 输出直方图统计结果
for i in range(len(hist)):print("灰度值 %d: %d 个像素" % (i, hist[i]))

3. 绘制直方图
# 绘制直方图
plt.bar(range(256), hist)
plt.show()

4. 直方图均衡化
使图片有更好的视觉效果,有更高的对比度,即像素的灰度分布更平均
首先,我们使用PIL库中的histogram()函数对灰度图像进行直方图统计,得到一个长度为256的列表equ_img,其中每个元素表示对应灰度级别的像素数量。
接着,我们创建一个空列表lut,用于保存灰度级别的映射表。然后,通过遍历equ_img列表,将每个灰度级别的像素数量除以255得到一个步长step,表示每个灰度级别在均衡化后的直方图中所占的比例。接下来,我们定义一个变量n,初始化为0,用于记录当前累积的像素数量。
在内层循环中,我们遍历256个灰度级别,并将当前累积的像素数量除以步长step得到一个映射值n / step。这个映射值表示当前灰度级别在均衡化后的直方图中所对应的灰度级别。
最后,我们使用PIL库中的point()方法,根据映射表lut将灰度图像进行映射,得到均衡化后的图像equ_img。在这里,lut列表中的值被用作灰度级别的映射,'L'参数表示输出图像的模式为灰度模式。
这样,经过直方图均衡化处理后,图像的灰度分布将更加均匀,增强了图像的对比度和细节。
# 直方图均衡化
equ_img = gray_img.histogram()
lut = []
for b in range(0, len(equ_img), 256):step = sum(equ_img[b:b+256]) / 255n = 0for i in range(256):lut.append(n / step)n += equ_img[b+i]
equ_img = gray_img.point(lut, 'L')# 显示原始图像和均衡化后的图像
plt.imshow(gray_img, cmap='gray')
plt.title('Original Image')
plt.axis('off')
plt.show()plt.imshow(equ_img, cmap='gray')
plt.title('Equalized Image')
plt.axis('off')
plt.show()# 保存原始图像和均衡化后的图像
gray_img.save('Original.jpg')
equ_img.save('Equalized.jpg')# 统计均衡化后的直方图
hist_equ = equ_img.histogram()# 绘制均衡化前后的直方图
plt.hist(gray_img.histogram(), 256, [0, 256])
plt.title('Original Image')
plt.xlim([0, 256])
plt.show()plt.hist(hist_equ, 256, [0, 256])
plt.title('Equalized Image')
plt.xlim([0, 256])
plt.show()




二、自适应直方图均衡化
自适应直方图均衡化(Adaptive Histogram Equalization)是直方图均衡化的一种变体,它考虑到图像中不同区域的局部差异。与直方图均衡化不同,自适应直方图均衡化将图像分成多个小块,并在每个小块内独立地应用直方图均衡化。通过这种方式,自适应直方图均衡化可以更好地保留图像的细节,并避免过度增强噪声。自适应直方图均衡化可以根据图像的局部特征自动调整每个小块的灰度级别,以实现更精细的图像增强。
1.自适应直方图均衡化(AHE)
AHE是一种局部直方图均衡化方法,它将图像分成若干个小区域,对每个小区域进行直方图均衡化处理,从而增强图像的对比度。该算法的核心思想是在每个小区域内计算直方图,并将其变换为累积分布函数(CDF),然后将CDF拉伸以增加对比度。因此,AHE可以有效地增强图像中的局部细节信息。
在此处,我们的输入参数包括原始图像img和窗口大小window_size。首先,函数遍历每个像素,获取以该像素为中心的大小为window_size的窗口。如果窗口越界,则跳过该像素。然后,计算窗口的直方图,并计算其累积分布函数。接着,将CDF归一化并拉伸,以增加窗口内像素的对比度。最后,将均衡化后的像素值放回原图中,得到均衡化后的结果。
# 自适应直方图均衡化(AHE)
def adaptive_histogram_equalization(img, window_size):# 获取图像大小height, width = img.shape[:2]# 创建一个全黑的图像result = np.zeros((height, width), dtype=np.uint8)# 遍历每个像素for i in range(height):for j in range(width):# 获取窗口中心点center_x, center_y = i + window_size // 2, j + window_size // 2# 如果窗口越界,则跳过if center_x < window_size // 2 or center_x >= height - window_size // 2 or center_y < window_size // 2 or center_y >= width - window_size // 2:continue# 获取窗口window = img[center_x - window_size // 2:center_x + window_size // 2 + 1, center_y - window_size // 2:center_y + window_size // 2 + 1]# 计算窗口的直方图hist, _ = np.histogram(window.ravel(), 256, [0, 256])# 计算累积分布函数cdf = hist.cumsum()# 归一化cdf_normalized = cdf * 255 / cdf[-1]# 将均衡化后的像素值放回原图中result[i][j] = cdf_normalized[img[i][j]]return result
2.限制对比度自适应直方图均衡化(CRHE)
CRHE是在AHE的基础上增加了对比度限制。它通过在AHE之后对像素值进行限制,以避免过度增加对比度而导致噪声的出现。该算法的核心思想是先使用AHE增强图像的对比度,然后使用限制对比度的方法对像素值进行截断,从而控制对比度的增加。
在代码中,输入参数包括原始图像img、窗口大小window_size和对比度限制因子clip_limit。首先,调用自己实现的自适应直方图均衡化函数adaptive_histogram_equalization对原始图像进行直方图均衡化处理,得到均衡化后的结果。接着,使用OpenCV库中的cv2.createCLAHE函数创建一个限制对比度的CLAHE对象,并将均衡化后的图像作为输入进行处理。
# 限制对比度自适应直方图均衡化(CRHE)
def contrast_limited_adaptive_histogram_equalization(img, window_size, clip_limit):# 使用自己实现的自适应直方图均衡化ahe_img = adaptive_histogram_equalization(img, window_size)# 使用OpenCV库实现限制对比度自适应直方图均衡化clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=(window_size, window_size))result = clahe.apply(ahe_img)return result
3.读取图片
# 读取图片
img = cv2.imread("image.jpg", cv2.IMREAD_GRAYSCALE)
4.自适应直方图均衡化
首先创建一个与原始图像img相同大小的全黑图像ahe_result,用于保存处理后的结果。然后,使用一个循环遍历多个窗口尺寸,依次调用自适应直方图均衡化函数adaptive_histogram_equalization对原始图像进行处理,并将处理后的结果加到ahe_result中。最后得到多个尺寸的均衡化结果的平均值,作为最终的均衡化结果。
我们使用了不同尺寸的窗口,分别为50、100、150和200。最后将这四个结果取平均值作为最终结果,这种方法可以提高均衡化的效果,因为不同尺寸的窗口可以捕捉到图像中不同尺度的局部细节信息,从而增强图像的对比度和细节信息,避免过大或过小的窗口对结果产生较大影响。
# 自适应直方图均衡化
# 创建一个和原始图像大小相同的全零数组ahe_result,用于存储最终的自适应直方图均衡化结果ahe_result = np.zeros_like(img)# 遍历不同的窗口大小,从50到200,步长为50
for window_size in range(50, 201, 50):# 对原始图像img进行自适应直方图均衡化操作,使用当前窗口大小window_sizeahe_img = adaptive_histogram_equalization(img, window_size)# 将每次处理后的图像ahe_img累加到ahe_result中ahe_result += ahe_img# 将ahe_result除以4取整,得到最终的自适应直方图均衡化结果
ahe_result //= 4
5.限制对比度自适应直方图均衡化
首先创建一个与原始图像img相同大小的全黑图像crhe_result,用于保存处理后的结果。然后,使用一个循环遍历多个窗口尺寸,依次调用限制对比度自适应直方图均衡化函数对原始图像进行处理,并将处理后的结果加到crhe_result中。在本例中,设置对比度限制因子clip_limit为2.0。
我们使用了不同尺寸的窗口,分别为50、100、150和200。最后将这四个结果取平均值作为最终结果,避免过大或过小的窗口对结果产生较大影响。
# 限制对比度自适应直方图均衡化
# 创建一个和原始图像大小相同的全零数组crhe_result,用于存储最终的限制对比度自适应直方图均衡化结果crhe_result = np.zeros_like(img)# 遍历不同的窗口大小,从50到200,步长为50
for window_size in range(50, 201, 50):# 对原始图像img进行限制对比度自适应直方图均衡化操作,使用当前窗口大小window_size和对比度限制参数2.0crhe_img = contrast_limited_adaptive_histogram_equalization(img, window_size, 2.0)# 将每次处理后的图像crhe_img累加到crhe_result中crhe_result += crhe_img# 将crhe_result除以4取整,得到最终的限制对比度自适应直方图均衡化结果
crhe_result //= 4
6.可视化显示结果
# 显示结果
fig, ax = plt.subplots(nrows=1, ncols=3, figsize=(12, 8))
ax[0].imshow(img, cmap='gray')
ax[0].set_title('Original1 Image')
ax[1].imshow(ahe_result, cmap='gray')
ax[1].set_title('AHE1 Image')
ax[2].imshow(crhe_result, cmap='gray')
ax[2].set_title('CRHE1 Image')
plt.show()

三、对比总结
直方图均衡化(Histogram Equalization)和自适应直方图均衡化(Adaptive Histogram Equalization)都是用于图像增强的技术,目的是改善图像的对比度和视觉效果。它们的主要区别在于处理图像的方式和局部性。
直方图均衡化是一种全局的方法,它基于整个图像的灰度直方图来调整像素的灰度值分布。通过使灰度级别在图像中更均匀地分布,直方图均衡化可以增强图像的对比度和细节。它使用累积分布函数将原始图像中的灰度级别映射到一个新的灰度范围,从而实现图像的均衡化。
然而,直方图均衡化是一种全局的方法,它没有考虑到图像中不同区域的局部差异。这可能会导致图像的某些区域过度增强或细节丢失的问题。为了解决这个问题,自适应直方图均衡化应运而生。
自适应直方图均衡化是一种局部的方法,在处理图像时会考虑到不同区域的灰度分布情况。它将图像分成许多小区域,对每个区域独立地应用直方图均衡化。通过这种方式,自适应直方图均衡化可以更好地保留图像细节,并避免过度放大噪声。
自适应直方图均衡化的一种常见变体是自适应直方图均衡化(CLAHE),它在每个小区域中使用对比度限制来防止过度放大噪声。CLAHE的核心思想是将图像分成许多小块,然后对每个小块进行局部直方图均衡化,并对像素值进行裁剪以限制对比度的增强程度。通过这种方式,CLAHE在增强图像细节的同时有效控制了噪声的增强。
总而言之,直方图均衡化是一种全局的方法,通过整个图像的灰度直方图来增强图像对比度。 而 自适应直方图均衡化是一种局部的方法,通过对图像的小块进行独立的直方图均衡化来增强图像,并通过对比度限制来控制噪声的放大。
相关文章:
直方图均衡化和自适应直方图均衡化
前言: Hello大家好,我是Dream。 均衡化是数字图像处理中常用的一种技术,用于增强图像的视觉效果和对比度。,今天我们将实现对同一张图像的直方图均衡化和自适应直方图均衡化处理,学习一下两者的的基本原理和实现过程&a…...
京东门详一码多端探索与实践 | 京东云技术团队
本文主要讲述京东门详业务在支撑过程中遇到的困境,面对问题我们在效率提升、质量保障等方向的探索和实践,在此将实践过程中问题解决的思路和方案与大家一起分享,也希望能给大家带来一些新的启发 一、背景 1.1、京东门详介绍 1.1.1、京东门…...
数据挖掘 | 零代码采集房源数据,支持自动翻页、数据排重等
1 前言 城市规划、商业选址等应用场景中经常会对地区房价、地域价值进行数据分析,其中地区楼盘房价是分析数据中重要的信息参考点,一些互联网网站上汇聚了大量房源信息,通过收集此类数据,能够对地区房价的分析提供参考依据。 如何…...
迪米特法则
迪米特法则,也称为最少知识原则(Law of Demeter),是面向对象设计中的一个原则,旨在降低对象之间的耦合性,提高系统的可维护性和可扩展性。该原则强调一个类不应该直接与其它不相关的类相互交互,…...
云积天赫|AIGC+营销的排头兵
AIGC生成式人工智能,正逐渐成为人们关注的焦点。AIGC的出现,标志着人工智能已经进入了一个全新的时代。AIGC的出现,也为营销行业带来了新的活力。那么企业该怎么利用这次AIGC浪潮,成为AIGC营销的排头兵呢? “…...
Oracle 数据库备份
1、使用管理员账号创建对应的directory目录 登录数据库 sqlplus / as sysdba 创建directory create or replace directory dumpdir as F:\container; 2、给用户赋予使用该目录的权限 grant read,write on directory dumpdir to Scott; 查看创建的目录位置 select * fro…...
【C++】模板template
🔥🔥 欢迎来到小林的博客!! 🛰️博客主页:✈️林 子 🛰️博客专栏:✈️ C 🛰️社区 :✈️ 进步学堂 🛰️欢…...
智能工厂:适应不断变化的制造世界
制造业已经从过去传统的装配线工艺流程中走了很长一段路。随着技术的进步和工业 4.0 的兴起,制造业正在迅速发展,以满足现代世界不断变化的需求。近年来出现的一个关键概念就是“智能工厂”。在这篇文章中,我们将探讨什么是智能工厂、它是如何…...
大数据课程I3——Kafka的消息流与索引机制
文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Kafka的消息流处理; ⚪ 掌握Kafka的索引机制; ⚪ 掌握Kafka的消息系统语义; 一、Kafka消息流处理 1. Producer 写入消息 流程说明: 1. producer 要向Kafka生产消息,需要先通过…...
LVGL学习笔记 28 - 键盘keyboard
目录 1. 设置关联文本框 2. 设置模式 2.1 LV_KEYBOARD_MODE_TEXT_LOWER 2.2 LV_KEYBOARD_MODE_TEXT_UPPER 2.3 LV_KEYBOARD_MODE_SPECIAL 2.4 LV_KEYBOARD_MODE_NUMBER 2.5 LV_KEYBOARD_MODE_USER_1 ~ LV_KEYBOARD_MODE_USER_4 3. 使能弹窗模式 4. 更改按键布局 5. 事…...
【Microsoft 支持】【数据库-MySql】当您尝试从大于 5000 的 TCP 端口连接时收到错误 WSAENOBUFS (10055)
一、转载原文 When you try to connect from TCP ports greater than 5000 you receive the error ‘WSAENOBUFS (10055)’ Symptoms If you try to set up TCP connections from ports that are greater than 5000, the local computer responds with the following WSAE…...
【学会动态规划】最长湍流子数组(23)
目录 动态规划怎么学? 1. 题目解析 2. 算法原理 1. 状态表示 2. 状态转移方程 3. 初始化 4. 填表顺序 5. 返回值 3. 代码编写 写在最后: 动态规划怎么学? 学习一个算法没有捷径,更何况是学习动态规划, 跟我…...
【网络编程·网络层】IP协议
目录 一、IP协议的概念 二、IP协议的报头 1、四位首部长度 2、16位总长度(解包) 3、8位协议(分用) 4、16位首部校验和 5、8位生存时间 6、32位源IP和32位目的IP 7、4位版本/8位服务类型 8、16位标识 9、3位标志 10、1…...
HTML详解连载(7)
HTML详解连载(7) 专栏链接 [link](http://t.csdn.cn/xF0H3)下面进行专栏介绍 开始喽结构伪类选择器作用 :nth-child(公式)作用举例 伪元素选择器作用注意: PxCoook作用盒子模型-重要组成部分 盒子模型-边框线属性名属性…...
一文打通redis中的String类型
目录 基本介绍 基本语法 常用命令解读 概述 SETNX key value SETNX key value GETRANGE key start end GETSET key value GETBIT key offset MGET key1 [key2..] STRLEN key 基本介绍 ①String是Redis最基本的类型,一个key对应一个value。 ②String类型是二进制…...
优测云服务平台|【压力测试功能升级】轻松完成压测任务
一、本次升级主要功能如下: 1.多份报告对比查看测试结果 2.报告新增多种下载格式 Word格式Excel格式 3.新增多种编排复杂场景的控制器 漏斗控制器并行控制器事务控制器仅一次控制器分组控制器集合点 4.新增概览页面,包含多种统计维度 二、报告对比…...
UseEffect中使用setState更新后获取的值为何依然是更新前
刚开始学习React的新手经常遇到这样的问题,使用useState去更新某个数据,然后再取更新后的数据,取发现数据并没有更新。 在 React 中,useState 的更新确实是异步的,这是由 React 的内部机制所决定的。React 会对多次状…...
去掉鼠标系列之一: 语雀快捷键使用指南
其实应该是系列之二了,因为前面写了一个关于Interlij IDEA的快捷键了。 为什么要写这个了,主要是觉得一会儿用鼠标,一会儿键盘,一点儿不酷,我希望可以一直用键盘,抛开鼠标。后面陆续记录一下各个软件的快捷…...
【Linux】Reactor模式
Reactor模式 Reactor模式的定义 Reactor反应器模式,也叫做分发者模式或通知者模式,是一种将就绪事件派发给对应服务处理程序的事件设计模式。 Reactor模式的角色构成 Reactor主要由以下五个角色构成: reactor模式的角色 角色解释Handle(句…...
【LeetCode 算法】Merge Two Binary Trees 合并二叉树
文章目录 Merge Two Binary Trees 合并二叉树问题描述:分析代码PreOrder DFSPreOrder Tag Merge Two Binary Trees 合并二叉树 问题描述: 给你两棵二叉树: root1 和 root2 。 想象一下,当你将其中一棵覆盖到另一棵之上时&#…...
Claude Code / Cursor 写的代码,你敢直接上线吗?我踩过一次坑,再也不敢
👉 这是一个或许对你有用的社群🐱 一对一交流/面试小册/简历优化/求职解惑,欢迎加入「芋道快速开发平台」知识星球。下面是星球提供的部分资料: 《项目实战(视频)》:从书中学,往事上…...
为什么93%的DeepSeek PR被拒?揭秘CI流水线自动拦截的4类“伪Clean”代码陷阱
更多请点击: https://intelliparadigm.com 第一章:为什么93%的DeepSeek PR被拒?揭秘CI流水线自动拦截的4类“伪Clean”代码陷阱 DeepSeek 开源仓库的 CI 流水线以严苛著称——最新统计显示,93% 的 PR 在 pre-commit 阶段即被自动…...
现实是期待的土壤,期待是改变现实的方向
期待的对立统一结构期待 理想应然(正题) vs 现实实然(反题),二者的统一构成一个动态的矛盾运动。同一性(相互依存):没有对现实的不满足和对未来的向往,就没有期待&#…...
Midjourney版本战争白皮书(V7终结篇 vs V8统治纪元):从token消耗策略、种子可控性、多主体一致性到商用合规链路的断代式升级
更多请点击: https://intelliparadigm.com 第一章:V7终结篇与V8统治纪元的战略分水岭 V7 版本的正式 EOL(End-of-Life)标志着一个技术周期的谢幕,而 V8 的全面 GA(General Availability)则开启…...
自然语言脚本编程:用humanscript实现意图驱动的自动化
1. 项目概述:当代码遇上自然语言最近在折腾一些自动化脚本时,我总在想,有没有一种方式,能让写脚本这件事变得像写待办事项清单一样简单?比如,我想让电脑“把今天下载的图片都压缩一下,然后传到网…...
基于Helm与Kubernetes的以太坊节点自动化部署与运维实战
1. 项目概述:当以太坊遇见Kubernetes如果你和我一样,在区块链基础设施领域摸爬滚打多年,从早期手动编译客户端、配置systemd服务,到后来用Docker Compose编排节点,每一步都伴随着大量的重复劳动和运维痛点。当节点数量…...
Dify数据库查询插件:让AI应用轻松连接业务数据的实战指南
1. 项目概述与核心价值 如果你正在使用 Dify 构建企业级 AI 应用,并且经常需要让 AI 助手去查询数据库里的数据——比如让 LLM 帮你分析销售报表、查找用户信息或者生成业务洞察——那么你很可能遇到过这样的痛点:Dify 本身并不直接支持数据库连接。你需…...
南京彩钢瓦屋面防水供应商
在南京,彩钢瓦屋面广泛应用于各类建筑,然而其防水问题一直是困扰众多业主的难题。选择一家靠谱的彩钢瓦屋面防水供应商至关重要。今天就为大家详细介绍雨中行修缮工程有限公司,同时也对比其他一些大厂,看看雨中行修缮为何能在市场…...
保姆级教程:用Intel官方工具搞定Realsense D435深度不准和黑点问题
深度视觉优化实战:Intel RealSense D435深度校准全流程解析 刚拆封的RealSense D435摄像头在深度模式下出现零星黑点?深度图某些区域数值明显失真?这些问题往往不是硬件缺陷,而是出厂校准参数与实际使用环境不匹配导致的。作为计算…...
教培机构管理越忙越乱?用对工具,比多雇两个人更高效
不少培训机构校长都有同样的感受:明明团队很拼,每天从早忙到晚,可机构依旧问题不断。招生线索散落在微信、表格、登记本里,跟进不及时就白白流失;排课全靠人工核对,老师冲突、教室撞期、调课通知不到位是常…...
