python实现图像对比度增强算法

python实现直方图均衡化、自适应直方图均衡化、连接组件标记算法

      • 1.直方图均衡化算法详解
        • 算法步骤
        • 公式
        • Python 实现
        • 详细解释
        • 优缺点
      • 2.自适应直方图均衡化算法详解
        • 算法步骤
        • 公式
        • Python 实现
        • 详细解释
        • 优缺点
      • 3.连接组件标记算法详解
        • 算法步骤
        • 8连通与4连通
        • 公式
        • Python 实现
        • 详细解释
        • 优缺点

1.直方图均衡化算法详解

直方图均衡化(Histogram Equalization)是一种用于增强图像对比度的技术。它通过调整图像的灰度值分布,使图像的灰度值更加均匀,从而提升图像的整体对比度。

算法步骤
  1. 计算原始图像的灰度直方图:统计图像中每个灰度值出现的次数。
  2. 计算累积分布函数(CDF):累积直方图。
  3. 应用均衡化公式:将原始图像中的每个灰度值映射到新的灰度值。
  4. 生成均衡化后的图像
公式

在这里插入图片描述

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()
详细解释
  1. 读取图像和转换为灰度图像

    image = Image.open('example.jpg')
    grayscale_image = image.convert("L")
    
  2. 计算灰度直方图

    image_array = np.array(grayscale_image)
    hist, bins = np.histogram(image_array.flatten(), bins=256, range=[0, 256])
    
  3. 计算累积分布函数(CDF)

    cdf = hist.cumsum()
    cdf_normalized = cdf * hist.max() / cdf.max()
    
  4. 使用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')
    
  5. 映射原始灰度值到新的灰度值

    equalized_image_array = cdf[image_array]
    equalized_image = Image.fromarray(equalized_image_array)
    
  6. 显示和保存均衡化后的图像

    equalized_image.show()
    equalized_image.save('equalized_example.jpg')
    
  7. 绘制直方图

    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通过对每个子块中的直方图进行剪裁,限制对比度增强的程度,从而减少噪声的引入。

算法步骤
  1. 将图像划分为多个子块:将图像分成多个不重叠的子块。
  2. 对每个子块进行直方图均衡化:计算每个子块的直方图和累积分布函数(CDF),并应用均衡化公式。
  3. 对每个子块进行对比度限制(CLAHE):对直方图进行剪裁,限制增强的对比度。
  4. 插值重构图像:对每个子块的均衡化结果进行双线性插值,重构整个图像。
公式

在这里插入图片描述

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')  # 保存均衡化后的图像
详细解释
  1. 读取图像和转换为灰度图像

    image = Image.open('example.jpg')
    grayscale_image = image.convert("L")
    
  2. 将灰度图像转换为NumPy数组

    image_array = np.array(grayscale_image)
    
  3. 创建CLAHE对象

    clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))
    
  4. 应用CLAHE算法

    equalized_image_array = clahe.apply(image_array)
    
  5. 将处理后的数组转换为图像

    equalized_image = Image.fromarray(equalized_image_array)
    
  6. 显示和保存均衡化后的图像

    equalized_image.show()
    equalized_image.save('equalized_example.jpg')
    
优缺点

优点

  • 增强局部对比度:能够有效增强图像的局部对比度,适用于对局部细节要求较高的图像。
  • 减少噪声引入:相比传统的AHE,CLAHE通过对比度限制减少了噪声的引入。

缺点

  • 计算复杂度高:由于需要对每个子块进行处理,计算复杂度较高。
  • 实现复杂:相比全局直方图均衡化,实现过程更复杂。

自适应直方图均衡化特别适用于那些需要增强局部对比度的应用场景,如医学影像、卫星图像等。CLAHE进一步改善了AHE的不足,使其在实际应用中更加实用。

3.连接组件标记算法详解

连接组件标记算法(Connected Component Labeling, CCL)是一种用于在二值图像中标识和分类不同连接组件的算法。连接组件是指图像中所有像素值相同且彼此相邻的像素组成的区域。CCL算法用于图像分割、物体检测和图像理解等任务中。

算法步骤
  1. 初始化标签:为每个像素初始化一个唯一的标签。
  2. 遍历图像:扫描图像的每个像素,根据邻域像素的标签更新当前像素的标签。
  3. 合并标签:在遍历过程中记录不同标签的合并关系,形成等价类。
  4. 第二次遍历:根据标签的合并关系,更新图像中的标签。
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()
详细解释
  1. 读取图像并转换为二值图像

    binary_image = cv2.threshold(image, 127, 255, cv2.THRESH_BINARY)[1]
    
  2. 初始化标签数组

    labels = np.zeros((rows, cols), dtype=int)
    label = 1  # 初始化标签
    
  3. 遍历图像并更新标签

    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
    
  4. 合并等价标签

    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
    
  5. 显示结果

    plt.imshow(labeled_image, cmap='jet')
    plt.title('Connected Component Labeling')
    plt.colorbar()
    plt.show()
    
优缺点

优点

  • 简单易实现:基础的CCL算法实现简单,适合初学者学习。
  • 有效分割前景和背景:能够有效分割图像中的不同连接组件。

缺点

  • 计算复杂度高:特别是在处理大图像时,计算复杂度较高。
  • 内存消耗大:需要额外的内存来存储标签和等价类信息。

连接组件标记算法在图像分割和物体检测中具有广泛的应用,特别适用于需要识别和分类图像中不同区域的任务。通过对等价标签的合并,可以有效地解决图像中的连通区域标记问题。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/874024.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

微服务实现全链路灰度发布

一、实现步骤 再请求 Header 中打上标签,例如再 Header 中添加 "gray-tag: true" ,其表示要进行灰度测试(访问灰度服务),而其他则访问正式服务。在负载均衡器 Spring Cloud LoadBalancer 中,拿到…

Deepin系统,中盛科技温湿度模块读温度纯c程序(备份)

#include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <termios.h>int main() {int fd;struct termios options;// 打开串口设备fd open("/dev/ttyMP0", O_RDWR | O_NOCTTY|O_NDELAY); //O_NDELAY:打开设备不阻塞//O_NOCTT…

Qt Creator配置以及使用Valgrind - 检测内存泄露

Qt Creator配置以及使用Valgrind - 检测内存泄露 引言一、下载安装1.1 下载源码1.2 安装 二、配置使用2.1 Qt Creator配置2.2 使用2.3 更多详细信息可参考官方文档&#xff1a; 三、参考链接 引言 Valgrind是一个在Linux平台下广泛使用的开源动态分析工具&#xff0c;它提供了一…

7Python的Pandas:基础操作

Pandas 是一个强大的 Python 数据分析工具库&#xff0c;它提供了许多便利的数据结构和数据操作方法。以下是一些常见的 Pandas 基础操作&#xff1a; 导入 Pandas 库&#xff1a; import pandas as pd创建 DataFrame&#xff1a; data {Name: [Alice, Bob, Charlie], Age: [2…

开启你的 Django 开发之旅:从环境搭建到服务部署

欢迎来到这个关于如何使用 Django、MySQL、HTML、CSS、Bootstrap、jQuery 和 ECharts 构建一个全栈 Web 应用的指南。在这个博客中&#xff0c;我们将从零开始&#xff0c;一步步地搭建开发环境&#xff0c;并最终将服务部署到 Linux 系统上。 本篇进介绍大概得步骤&am…

任务2:python+InternStudio 关卡

任务地址 https://github.com/InternLM/Tutorial/blob/camp3/docs/L0/Python/task.md 文档 https://github.com/InternLM/Tutorial/tree/camp3/docs/L0/Python 任务 Python实现wordcount import re import collectionstext """ Got this panda plush to…

【机器学习】智能驱动未来:机器学习在能源效率提升与环境管理中的创新应用

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀目录 &#x1f50d;1. 引言&#x1f4d2;2. 机器学习能源环境领域的应用潜力&#x1f304;能源效率提升&#x1f3de;️环境管理⛰️具体案例…

Linux之旅:常用的指令,热键和权限管理

目录 前言 1. Linux指令 &#xff08;1&#xff09; ls &#xff08;2&#xff09; pwd 和 cd &#xff08;3&#xff09;touch 和 mkdir &#xff08;4&#xff09; rmdir 和 rm &#xff08;5&#xff09;cp &#xff08;6&#xff09;mv &#xff08;7&#xff09;…

开发工具推荐:await-to-js

目录 前言&#xff1a; 1. .then().catch() 2. async await 3. await-to-js 前言&#xff1a; 今天给大家推荐一块我觉得用着还不错的工具&#xff0c;await-to-js&#xff1b; await-to-js - npm GitHub - scopsy/await-to-js: Async await wrapper for easy error ha…

HTML+CSS+JS精美气泡提示框

源代码在效果图后面 点赞❤️关注&#x1f49b;收藏⭐️ 主要实现&#xff1a;提示框出现和消失两种丝滑动画 弹出气泡提示框后延迟2秒自动消失 效果图 错误框 正确 警告 提示 源代码 <!DOCTYPE html> <html lang"en"> <head><meta cha…

PHP场地预约共享茶室棋牌室小程序系统源码

&#x1f375;&#x1f3b2;【聚会新宠】场地预约神器&#xff0c;共享茶室棋牌室小程序大揭秘&#xff01;&#x1f389; &#x1f3e1;【开篇&#xff1a;告别繁琐&#xff0c;聚会新选择】&#x1f3e1; 还在为找不到合适的聚会场地而烦恼吗&#xff1f;想要一个既私密又舒…

【如何在Python中插入列表元素】

在Python中&#xff0c;插入列表元素可以通过多种方式实现&#xff0c;具体取决于你想要将元素插入到列表的哪个位置。以下是一些常用的方法&#xff1a; 1. 使用append()方法 append()方法用于在列表的末尾添加一个元素。这是插入元素到列表中最简单的方式。 my_list [1, …

JS 原型与原型链图解:彻底搞懂的终极指南

前言 &#x1f4eb; 大家好&#xff0c;我是南木元元&#xff0c;热爱技术和分享&#xff0c;欢迎大家交流&#xff0c;一起学习进步&#xff01; &#x1f345; 个人主页&#xff1a;南木元元 在JavaScript中&#xff0c;原型和原型链是非常重要的知识点&#xff0c;只有理解了…

2.2.填充和步幅

我们已经知道&#xff0c;卷积的输出形式取决于输入形式和卷积核的形式。 ​ 此外还有其他因素会影响输出的大小。假设以下情景&#xff1a; 有时&#xff0c;在应用了连续的卷积之后&#xff0c;我们最终得到的输出远小于输入大小。这是由于卷积核的宽度和高度通常大于1所导致…

驱动框架——CMSIS第一部分 RTE驱动框架介绍

一、介绍CMISIS 什么是CMSIS&#xff08;cortex microcontrol software interface standard一种软件标准接口&#xff09;&#xff0c;官网地址&#xff1a;https://arm-software.github.io/CMSIS_6/latest/General/index.html 包含的core、driver、RTOS、dsp、nn等部分&…

如何评价《系统之美》这本书

系统的总体大于部分之和&#xff0c;因而&#xff1a;一万个图书管理员也无法取代一个搜索引擎 一万个图书管理员简单的拼凑在一起构不成一个系统&#xff0c;而搜索引擎却是个可以不断完善的系统。生物学中对于系统的定义是&#xff1a;“系统是能够完成一种或者几种生理功能…

Linux系统编程:自定义协议(序列化和反序列化)

1. 协议 在之前我们谈到&#xff0c;协议就是一种"约定"&#xff0c;socket api接口&#xff0c;在读写数据时&#xff0c;都是按照"字符串"的方式来发送接收的&#xff0c;那么我们要传输一些"结构化"数据时怎么办呢&#xff1f;,比如说一个结构…

前端-04-VScode敲击键盘有键入音效,怎么关闭

目录 问题解决办法 问题 今天正在VScode敲项目&#xff0c;不知道是按了什么快捷键还是什么的&#xff0c;敲击键盘有声音&#xff0c;超级烦人啊&#xff01;&#xff01;于是我上网查了一下&#xff0c;应该是开启了VScode的键入音效&#xff0c;下面是关闭键入音效的办法。…

kafka---消息日志详解

一、Log Flush Policy&#xff08;log flush 策略&#xff09; 1、设置内存中保留日志的个数&#xff0c;当达到这个数量的时候&#xff0c;内存中的数据会被强制刷到disk中 log.flush.interval.messages10000 2、设置内存中保留日志的时间&#xff0c;当达到这个时间的时候&am…

DP刷题(1500-1700)

1.区间DP&#xff1a;https://www.acwing.com/problem/content/323/ 比较容易想到区间DP,转换一下均方差定义用记忆化搜索就可以了。 下面是AC代码&#xff1a; #include<bits/stdc.h> using namespace std; const int N 16; int n, m 8; int s[N][N]; double f[N][…