python实现图像对比度增强算法
python实现直方图均衡化、自适应直方图均衡化、连接组件标记算法
- 1.直方图均衡化算法详解
- 算法步骤
- 公式
- Python 实现
- 详细解释
- 优缺点
- 2.自适应直方图均衡化算法详解
- 算法步骤
- 公式
- Python 实现
- 详细解释
- 优缺点
- 3.连接组件标记算法详解
- 算法步骤
- 8连通与4连通
- 公式
- Python 实现
- 详细解释
- 优缺点
1.直方图均衡化算法详解
直方图均衡化(Histogram Equalization)是一种用于增强图像对比度的技术。它通过调整图像的灰度值分布,使图像的灰度值更加均匀,从而提升图像的整体对比度。
算法步骤
- 计算原始图像的灰度直方图:统计图像中每个灰度值出现的次数。
- 计算累积分布函数(CDF):累积直方图。
- 应用均衡化公式:将原始图像中的每个灰度值映射到新的灰度值。
- 生成均衡化后的图像。
公式
Python 实现
以下是直方图均衡化算法的Python实现代码:
import numpy as np
from PIL import Image
import matplotlib.pyplot as pltdef histogram_equalization(image):# 将图像转换为灰度图像grayscale_image = image.convert("L")image_array = np.array(grayscale_image)# 计算灰度直方图hist, bins = np.histogram(image_array.flatten(), bins=256, range=[0, 256])# 计算累积分布函数(CDF)cdf = hist.cumsum()cdf_normalized = cdf * hist.max() / cdf.max() # 归一化# 使用累积分布函数(CDF)进行均衡化cdf_min = cdf.min()cdf_m = np.ma.masked_equal(cdf, 0)cdf_m = (cdf_m - cdf_min) * 255 / (cdf.max() - cdf_min)cdf = np.ma.filled(cdf_m, 0).astype('uint8')# 将均衡化后的灰度值映射到原始图像equalized_image_array = cdf[image_array]equalized_image = Image.fromarray(equalized_image_array)return equalized_image# 示例用法
if __name__ == "__main__":image = Image.open('example.jpg') # 打开原始图像equalized_image = histogram_equalization(image) # 调用直方图均衡化函数equalized_image.show() # 显示均衡化后的图像equalized_image.save('equalized_example.jpg') # 保存均衡化后的图像# 绘制原始图像和均衡化后的直方图plt.figure()plt.subplot(121)plt.title('Original Image Histogram')plt.hist(np.array(image.convert("L")).flatten(), bins=256, range=[0, 256], color='black')plt.subplot(122)plt.title('Equalized Image Histogram')plt.hist(np.array(equalized_image).flatten(), bins=256, range=[0, 256], color='black')plt.show()
详细解释
-
读取图像和转换为灰度图像:
image = Image.open('example.jpg') grayscale_image = image.convert("L")
-
计算灰度直方图:
image_array = np.array(grayscale_image) hist, bins = np.histogram(image_array.flatten(), bins=256, range=[0, 256])
-
计算累积分布函数(CDF):
cdf = hist.cumsum() cdf_normalized = cdf * hist.max() / cdf.max()
-
使用CDF进行均衡化:
cdf_min = cdf.min() cdf_m = np.ma.masked_equal(cdf, 0) cdf_m = (cdf_m - cdf_min) * 255 / (cdf.max() - cdf_min) cdf = np.ma.filled(cdf_m, 0).astype('uint8')
-
映射原始灰度值到新的灰度值:
equalized_image_array = cdf[image_array] equalized_image = Image.fromarray(equalized_image_array)
-
显示和保存均衡化后的图像:
equalized_image.show() equalized_image.save('equalized_example.jpg')
-
绘制直方图:
plt.subplot(121) plt.title('Original Image Histogram') plt.hist(np.array(image.convert("L")).flatten(), bins=256, range=[0, 256], color='black') plt.subplot(122) plt.title('Equalized Image Histogram') plt.hist(np.array(equalized_image).flatten(), bins=256, range=[0, 256], color='black') plt.show()
优缺点
优点:
- 增强对比度:提高图像的整体对比度,使细节更加清晰。
- 实现简单:算法简单,易于实现。
缺点:
- 可能引入噪声:在一些情况下,可能会引入不必要的噪声。
- 不适用于所有图像:对于已经具有良好对比度的图像,效果可能不明显。
直方图均衡化是一种简单且有效的图像增强技术,适用于提升图像对比度的应用场景。
2.自适应直方图均衡化算法详解
自适应直方图均衡化(Adaptive Histogram Equalization, AHE)是一种改进的直方图均衡化方法,它在局部区域内(即图像的子块)进行直方图均衡化,而不是对整个图像进行全局均衡化。这种方法可以更好地增强图像的局部对比度,但也可能会引入噪声。
对比度受限的自适应直方图均衡化(Contrast Limited Adaptive Histogram Equalization, CLAHE)是AHE的一种改进版本。CLAHE通过对每个子块中的直方图进行剪裁,限制对比度增强的程度,从而减少噪声的引入。
算法步骤
- 将图像划分为多个子块:将图像分成多个不重叠的子块。
- 对每个子块进行直方图均衡化:计算每个子块的直方图和累积分布函数(CDF),并应用均衡化公式。
- 对每个子块进行对比度限制(CLAHE):对直方图进行剪裁,限制增强的对比度。
- 插值重构图像:对每个子块的均衡化结果进行双线性插值,重构整个图像。
公式
Python 实现
以下是自适应直方图均衡化(CLAHE)的Python实现代码:
import cv2
import numpy as np
from PIL import Imagedef adaptive_histogram_equalization(image, clip_limit=2.0, grid_size=(8, 8)):"""自适应直方图均衡化 (CLAHE) 算法实现参数:image (PIL.Image): 输入图像clip_limit (float): 对比度限制grid_size (tuple): 网格大小返回:PIL.Image: 均衡化后的图像"""# 将图像转换为灰度图像grayscale_image = image.convert("L")image_array = np.array(grayscale_image)# 创建CLAHE对象clahe = cv2.createCLAHE(clipLimit=clip_limit, tileGridSize=grid_size)# 应用CLAHE算法equalized_image_array = clahe.apply(image_array)# 将处理后的数组转换为图像equalized_image = Image.fromarray(equalized_image_array)return equalized_image# 示例用法
if __name__ == "__main__":image = Image.open('example.jpg') # 打开原始图像equalized_image = adaptive_histogram_equalization(image) # 调用自适应直方图均衡化函数equalized_image.show() # 显示均衡化后的图像equalized_image.save('equalized_example.jpg') # 保存均衡化后的图像
详细解释
-
读取图像和转换为灰度图像:
image = Image.open('example.jpg') grayscale_image = image.convert("L")
-
将灰度图像转换为NumPy数组:
image_array = np.array(grayscale_image)
-
创建CLAHE对象:
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
-
应用CLAHE算法:
equalized_image_array = clahe.apply(image_array)
-
将处理后的数组转换为图像:
equalized_image = Image.fromarray(equalized_image_array)
-
显示和保存均衡化后的图像:
equalized_image.show() equalized_image.save('equalized_example.jpg')
优缺点
优点:
- 增强局部对比度:能够有效增强图像的局部对比度,适用于对局部细节要求较高的图像。
- 减少噪声引入:相比传统的AHE,CLAHE通过对比度限制减少了噪声的引入。
缺点:
- 计算复杂度高:由于需要对每个子块进行处理,计算复杂度较高。
- 实现复杂:相比全局直方图均衡化,实现过程更复杂。
自适应直方图均衡化特别适用于那些需要增强局部对比度的应用场景,如医学影像、卫星图像等。CLAHE进一步改善了AHE的不足,使其在实际应用中更加实用。
3.连接组件标记算法详解
连接组件标记算法(Connected Component Labeling, CCL)是一种用于在二值图像中标识和分类不同连接组件的算法。连接组件是指图像中所有像素值相同且彼此相邻的像素组成的区域。CCL算法用于图像分割、物体检测和图像理解等任务中。
算法步骤
- 初始化标签:为每个像素初始化一个唯一的标签。
- 遍历图像:扫描图像的每个像素,根据邻域像素的标签更新当前像素的标签。
- 合并标签:在遍历过程中记录不同标签的合并关系,形成等价类。
- 第二次遍历:根据标签的合并关系,更新图像中的标签。
8连通与4连通
- 4连通:每个像素与上下左右四个像素相邻。
- 8连通:每个像素与周围八个像素相邻。
公式
Python 实现
以下是连接组件标记算法的Python实现代码:
import numpy as np
import cv2
from matplotlib import pyplot as pltdef connected_component_labeling(image):"""连接组件标记算法实现参数:image (numpy.ndarray): 二值图像返回:numpy.ndarray: 标记后的图像"""# 将图像转换为二值图像binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)[1]# 获取图像的行和列rows, cols = binary_image.shape# 初始化标签数组labels = np.zeros((rows, cols), dtype=int)label = 1 # 初始化标签# 记录等价类label_equivalence = {}# 遍历图像for i in range(rows):for j in range(cols):if binary_image[i, j] == 255: # 如果当前像素为前景像素# 获取邻域像素的标签neighbors = []if i > 0 and labels[i-1, j] > 0:neighbors.append(labels[i-1, j])if j > 0 and labels[i, j-1] > 0:neighbors.append(labels[i, j-1])if neighbors:min_label = min(neighbors)labels[i, j] = min_labelfor neighbor in neighbors:if neighbor != min_label:if neighbor in label_equivalence:label_equivalence[neighbor].add(min_label)else:label_equivalence[neighbor] = {min_label}if min_label in label_equivalence:label_equivalence[min_label].add(neighbor)else:label_equivalence[min_label] = {neighbor}else:labels[i, j] = labellabel += 1# 合并等价标签for i in range(rows):for j in range(cols):if labels[i, j] in label_equivalence:min_equivalent_label = min(label_equivalence[labels[i, j]])labels[i, j] = min_equivalent_labelreturn labels# 示例用法
if __name__ == "__main__":# 创建一个简单的二值图像binary_image = np.array([[0, 0, 0, 255, 255, 0, 0, 0],[0, 255, 255, 255, 255, 255, 0, 0],[0, 255, 255, 255, 255, 255, 255, 0],[0, 0, 0, 255, 255, 0, 0, 0],[0, 0, 0, 0, 0, 0, 0, 0],[0, 0, 255, 255, 0, 0, 0, 0],[0, 255, 255, 255, 255, 0, 0, 0],[0, 0, 0, 255, 0, 0, 0, 0]], dtype=np.uint8)labeled_image = connected_component_labeling(binary_image)# 显示结果plt.imshow(labeled_image, cmap='jet')plt.title('Connected Component Labeling')plt.colorbar()plt.show()
详细解释
-
读取图像并转换为二值图像:
binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)[1]
-
初始化标签数组:
labels = np.zeros((rows, cols), dtype=int) label = 1 # 初始化标签
-
遍历图像并更新标签:
for i in range(rows):for j in range(cols):if binary_image[i, j] == 255: # 如果当前像素为前景像素neighbors = []if i > 0 and labels[i-1, j] > 0:neighbors.append(labels[i-1, j])if j > 0 and labels[i, j-1] > 0:neighbors.append(labels[i, j-1])if neighbors:min_label = min(neighbors)labels[i, j] = min_labelfor neighbor in neighbors:if neighbor != min_label:if neighbor in label_equivalence:label_equivalence[neighbor].add(min_label)else:label_equivalence[neighbor] = {min_label}if min_label in label_equivalence:label_equivalence[min_label].add(neighbor)else:label_equivalence[min_label] = {neighbor}else:labels[i, j] = labellabel += 1
-
合并等价标签:
for i in range(rows):for j in range(cols):if labels[i, j] in label_equivalence:min_equivalent_label = min(label_equivalence[labels[i, j]])labels[i, j] = min_equivalent_label
-
显示结果:
plt.imshow(labeled_image, cmap='jet') plt.title('Connected Component Labeling') plt.colorbar() plt.show()
优缺点
优点:
- 简单易实现:基础的CCL算法实现简单,适合初学者学习。
- 有效分割前景和背景:能够有效分割图像中的不同连接组件。
缺点:
- 计算复杂度高:特别是在处理大图像时,计算复杂度较高。
- 内存消耗大:需要额外的内存来存储标签和等价类信息。
连接组件标记算法在图像分割和物体检测中具有广泛的应用,特别适用于需要识别和分类图像中不同区域的任务。通过对等价标签的合并,可以有效地解决图像中的连通区域标记问题。
相关文章:

python实现图像对比度增强算法
python实现直方图均衡化、自适应直方图均衡化、连接组件标记算法 1.直方图均衡化算法详解算法步骤公式Python 实现详细解释优缺点 2.自适应直方图均衡化算法详解算法步骤公式Python 实现详细解释优缺点 3.连接组件标记算法详解算法步骤8连通与4连通公式Python 实现详细解释优缺…...

【D3.js in Action 3 精译_020】2.6 用 D3 设置与修改元素样式 + 名人专访(Nadieh Bremer)+ 2.7 本章小结
当前内容所在位置 第一部分 D3.js 基础知识 第一章 D3.js 简介(已完结) 1.1 何为 D3.js?1.2 D3 生态系统——入门须知1.3 数据可视化最佳实践(上)1.3 数据可视化最佳实践(下)1.4 本章小结 第二章…...

GIT命令学习 二
📑打牌 : da pai ge的个人主页 🌤️个人专栏 : da pai ge的博客专栏 ☁️宝剑锋从磨砺出,梅花香自苦寒来 ☁️运维工程师的职责:监…...
LeetCode 150, 112, 130
文章目录 150. 逆波兰表达式求值题目链接标签思路代码 112. 路径总和题目链接标签思路代码 130. 被围绕的区域题目链接标签思路代码 150. 逆波兰表达式求值 题目链接 150. 逆波兰表达式求值 标签 栈 数组 数学 思路 本题很像 JVM 中的 操作数栈,当写出以下三行…...
c++应用网络编程之五Windows常用的网络IO模型
一、Windows的网络编程 其实对开发者而言,只有Windows和其它平台。做为一种普遍流行的图形OS,其一定会与类Linux的编程有着明显的区别,这点当然也会体现在网络编程上。Windows有着自己一套相对独立的上层Socket编程模型或者说框架࿰…...

PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动?
🍅关注博主🎗️ 带你畅游技术世界,不错过每一次成长机会!📚领书:PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动一、理解索引抖动二、索引抖动的影响三…...

鑫创SSS1700USB音频桥芯片USB转IIS芯片
鑫创SSS1700支持IIC初始外部编(EEPROM选项),两线串行总线(I2C总线)用于外部MCU控制整个EEPROM空间可以通过MCU访问用于主机控制同步的USB HID外部串行EEPROM(24C02~24C16)接口,用于客户特定的USB视频、PID、…...
计算机视觉发展历程
文章目录 前言一、发展历程1)、萌芽期(1960s-1970s)2)、基础发展期(1980s)3)、系统开发期(1990s-2000s)4)、深度学习兴起期(2010s)5&a…...

从安装Node到TypeScript到VsCode的配置教程
从安装Node到TypeScript到VsCode的配置教程 1.下载Node安装包, 链接 2.双击安装包,选择安装路径,如下: 3.一直点击下一步,直至安装结束即可: 这个时候,node会默认配置好环境变量,并且…...

Jackson详解
文章目录 一、Jackson介绍二、基础序列化和反序列化1、快速入门2、序列化API3、反序列化API4、常用配置 三、常用注解1、JsonProperty2、JsonAlias3、JsonIgnore4、JsonIgnoreProperties5、JsonFormat6、JsonPropertyOrder 四、高级特性1、处理泛型1.1、反序列化List泛型1.2、反…...

【算法】字符串
快乐的流畅:个人主页 个人专栏:《算法神殿》《数据结构世界》《进击的C》 远方有一堆篝火,在为久候之人燃烧! 文章目录 引言一、最长公共前缀二、最长回文子串三、二进制求和四、字符串相乘 引言 字符串题,大多数是模…...

Python酷库之旅-第三方库Pandas(037)
目录 一、用法精讲 116、pandas.Series.div方法 116-1、语法 116-2、参数 116-3、功能 116-4、返回值 116-5、说明 116-6、用法 116-6-1、数据准备 116-6-2、代码示例 116-6-3、结果输出 117、pandas.Series.truediv方法 117-1、语法 117-2、参数 117-3、功能 …...
iOS 左滑返回事件的控制
0x00 视图结构 1-根视图 1.1-控制器A 1.1.1-控制器B 1.1.1.1-控制器C 0x01 控制 通过设置 self.navigationController.interactivePopGestureRecognizer.enabled 为 YES 或 NO 来控制当面界面,是否能左滑返回 在 控制器B 的生命周期方法内,设置属性 s…...

= null 和 is null;SQL中关于NULL处理的4个陷阱;三值逻辑
一、概述 1、NULL参与的所有的比较和算术运算符(>,,<,<>,<,>,,-,*,/) 结果为unknown; 2、unknown的逻辑运算(AND、OR、NOT)遵循三值运算的真值表; 3、如果运算结果直接返回用户,使用NULL来标识unknown 4、如…...

拖拽上传(预览图片)
需求 点击上传图片,或直接拖拽图片到红色方框里面也可上传图片,上传后预览图片 效果 实现 <!DOCTYPE html> <html lang"zh-cn"><head><meta charset"UTF-8"><meta name"viewport" content&…...
Oracle 12c新特性 In-Memory Column Store
Oracle 12c引入了一项重要的特性——In-Memory Column Store(简称IM或In-Memory),这一特性极大地提升了数据库在处理分析型查询时的性能。以下是关于Oracle 12c In-Memory特性的详细介绍: 一、基本概念 In-Memory Column Store&…...

【数据结构】二叉树———Lesson2
Hi~!这里是奋斗的小羊,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~ 💥💥个人主页:奋斗的小羊 💥💥所属专栏:C语言 🚀本系列文章为个人学习…...

mongodb数据导出与导入
一、先去检查mongodump mongodump --version 如果报 mongodump version: built-without-version-string 或者其他的较老的版本,直接去下载最新的【传送门】 【以Ubuntu18.04为例】 安装工具 假设你下载的是 .tgz 文件(适用于 Linux 系统)&am…...

电路学习——经典运放电路之滞回比较器(施密特触发器)(2024.07.18)
参考链接1: 电子设计教程29:滞回比较器(施密特触发器) 参考链接2: 滞回比较器电路详细分析 参考链接3: 比较器精髓:施密特触发器,正反馈的妙用 参考链接4: 比较器反馈电阻选多大?理解滞后效应,轻…...

NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker)
NVIDIA Container Toolkit 安装与配置帮助文档(Ubuntu,Docker) 本文档详细介绍了在 Ubuntu Server 22.04 上使用 Docker 安装和配置 NVIDIA Container Toolkit 的过程。 概述 NVIDIA 容器工具包使用户能够构建和运行 GPU 加速容器。即可以在容器中使用NVIDIA显卡。 架构图如…...
Linux链表操作全解析
Linux C语言链表深度解析与实战技巧 一、链表基础概念与内核链表优势1.1 为什么使用链表?1.2 Linux 内核链表与用户态链表的区别 二、内核链表结构与宏解析常用宏/函数 三、内核链表的优点四、用户态链表示例五、双向循环链表在内核中的实现优势5.1 插入效率5.2 安全…...
云计算——弹性云计算器(ECS)
弹性云服务器:ECS 概述 云计算重构了ICT系统,云计算平台厂商推出使得厂家能够主要关注应用管理而非平台管理的云平台,包含如下主要概念。 ECS(Elastic Cloud Server):即弹性云服务器,是云计算…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享
文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的,根据Excel列的需求预估的工时直接打骨折,不要问我为什么,主要…...

srs linux
下载编译运行 git clone https:///ossrs/srs.git ./configure --h265on make 编译完成后即可启动SRS # 启动 ./objs/srs -c conf/srs.conf # 查看日志 tail -n 30 -f ./objs/srs.log 开放端口 默认RTMP接收推流端口是1935,SRS管理页面端口是8080,可…...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
Python如何给视频添加音频和字幕
在Python中,给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加,包括必要的代码示例和详细解释。 环境准备 在开始之前,需要安装以下Python库:…...

12.找到字符串中所有字母异位词
🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》
这段 Python 代码是一个完整的 知识库数据库操作模块,用于对本地知识库系统中的知识库进行增删改查(CRUD)操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 📘 一、整体功能概述 该模块…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...