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

news2024/9/21 11:00:45

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 plt

def 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 Image

def 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 plt

def 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_label
                    for 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] = label
                    label += 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
    
    return 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_label
                    for 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] = label
                    label += 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.coloradmin.cn/o/1939121.html

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

相关文章

Qt 使用Installer Framework制作安装包

Qt 使用Installer Framework制作安装包 引言一、下载安装 Qt Installer Framework二、简单使用2.1 创建目录结构 (文件夹结构)2.2 制作程序压缩包2.3 制作程序安装包 引言 Qt Installer Framework (安装程序框架)是一个强大的工具集,用于创建自定义的在线和离线安装…

DP-适配器模式代码重新理解

package com.designpatterns.adapter;/*** 定义鸭子接口*/ public interface Duck {/*** 定义鸭子呱呱叫(quack)*/public void quack();public void fly(); }package com.designpatterns.adapter;/*** 实现一个绿头鸭*/ public class MallarDuck implements Duck{Overridepubl…

德国汉堡大学、清华大学联合英国布里斯托机器人实验室的研究工作分享:基于视觉遥操作的多指机械手灵巧操作

德国汉堡大学(张建伟院士团队)、清华大学(孙富春教授和方斌)联合英国布里斯托机器人实验室等单位在基于视觉信息遥操作的多指机械手灵巧操作研究方面取得进展。该工作得到了德国科学基金会(DFG)与中国国家自…

C++合作开发项目:美术馆1.0

快乐星空MakerZINCFFO 合作入口&#xff1a;CM工作室 效果图&#xff1a; 代码&#xff1a; &#xff08;还有几个音乐&#xff01;&#xff09; main.cpp #include <bits/stdc.h> #include <windows.h> #include <conio.h> #include <time.h> #in…

E16.【C语言】练习:输入一个正的整数,逆序打印这个整数的每一位

输入一个正的整数&#xff0c;逆序打印这个整数的每一位 输入&#xff1a;123 输出&#xff1a;321 步骤&#xff1a;1.取出整数的每一位 2.倒序打印 分析&#xff1a;123%103-->123/1012(3被去除了)-->12%102-->12/101(2被去除了)-->1%101(取出最后一位)->…

Michael.W基于Foundry精读Openzeppelin第66期——ProxyAdmin.sol

Michael.W基于Foundry精读Openzeppelin第66期——ProxyAdmin.sol 0. 版本0.1 ProxyAdmin.sol 1. 目标合约2. 代码精读2.1 getProxyImplementation(ITransparentUpgradeableProxy proxy)2.2 getProxyAdmin(ITransparentUpgradeableProxy proxy) && changeProxyAdmin(ITr…

【计算机网络】0 课程主要内容(自顶向下方法,中科大郑烇、杨坚)(待)

1 教学目标 掌握计算机网络 基本概念 工作原理 常用技术 为将来学习、应用和研究计算机网络打下坚实基础 2 课程主要内容 1 计算机网络和互联网2 应用层3 传输层4 网络层&#xff1a;数据平面5 网络层&#xff1a;控制平面6 数据链路层和局域网7 网络安全8 无线和移动网络9 多…

C2W1.LAB.Vocabulary Creation+Candidates from String Edits

理论课&#xff1a;C2W1.Auto-correct 文章目录 Vocabulary CreationImports and DataPreprocessingCreate Vocabulary法1.集合法法2.词典加词频法Visualization Ungraded Exercise Candidates from String EditsImports and DataSplitsDelete Edit Ungraded Exercise 理论课&…

Linux_实现线程池

目录 1、线程池的实现逻辑 2、创建多线程 3、对线程池分配任务 3.1 任务类 3.2 发送与接收任务 结语 前言&#xff1a; 在Linux下实现一个线程池&#xff0c;线程池就是创建多个线程&#xff0c;然后对这些线程进行管理&#xff0c;并且可以发放任务给到线程池…

【springboot】中使用--WebMvcConfigurer

WebMvcConfigurer 一、页面跳转控制器step1:创建视图&#xff0c;resources/templates/index.htmlstep2:创建SpringMVC配置类step3:测试功能 二、数据格式化step1:创建 DeviceInfo 数据类step2&#xff1a;自定义 Formatterstep3: 登记自定义的 DeviceFormatterstep4: 新建 Con…

杭州外贸网站建设 最好用wordpress模板来搭建

防护服wordpress外贸网站模板 消防服、防尘服、隔热服、防化服、防静电服、电焊服wordpress外贸网站模板。 https://www.jianzhanpress.com/?p4116 工业品wordpress外贸网站模板 机械及行业设备、五金工具、安全防护、包装、钢铁、纺织皮革等工业品wordpress外贸网站模板。…

实现高效离职管理,智慧校园人事管理功能全解析

智慧校园人事管理系统中的离职管理功能&#xff0c;为教职工提供了一个高效、透明且合规的离职流程&#xff0c;同时为学校管理层提供了优化人力资源配置的有力工具。教职工可以在线轻松提交离职申请&#xff0c;系统随即自动记录并启动后续流程&#xff0c;从申请审核到工作交…

C语言 | Leetcode C语言题解之第241题为运算表达式设计优先级

题目&#xff1a; 题解&#xff1a; #define ADDITION -1 #define SUBTRACTION -2 #define MULTIPLICATION -3int* diffWaysToCompute(char * expression, int* returnSize) {int len strlen(expression);int *ops (int *)malloc(sizeof(int) * len);int opsSize 0;for (in…

任务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…

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

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

ARM体系结构和接口技术(九)异常

文章目录 &#xff08;一&#xff09;异常模式&#xff08;二&#xff09;Cortex-A7核的异常处理流程分析1. 保存现场&#xff08;系统自动完成&#xff09;2. 恢复现场&#xff08;程序员手动完成&#xff09;3. 异常处理流程 &#xff08;三&#xff09;软中断验证异常处理函…

谷粒商城实战笔记-40-前端基础-Vue-计算属性、监听器、过滤器

文章目录 一&#xff0c;计算属性1&#xff0c;用途2&#xff0c;用法2.1 定义View2.2 声明计算属性 3&#xff0c;注意事项 二&#xff0c;监听器1. 使用 watch 监听属性的变化 三&#xff0c;过滤器1&#xff0c;定义局部过滤器2&#xff0c;定义全局过滤器3&#xff0c;使用…

level 6 day2-3 网络基础2---TCP编程

1.socket&#xff08;三种套接字&#xff1a;认真看&#xff09; 套接字就是在这个应用空间和内核空间的一个接口&#xff0c;如下图 原始套接字可以从应用层直接访问到网络层&#xff0c;跳过了传输层&#xff0c;比如在ubtan里面直接ping 一个ip地址,他没有经过TCP或者UDP的数…

如何修复 CrowdStrike 蓝屏错误 Windows 11

如果您的 PC 出现 BSoD 错误&#xff0c;您不是唯一一个&#xff0c;但这里有一个解决方法来缓解该问题。 如果您有一台运行 Windows 11&#xff08;或 10&#xff09;的计算机使用 CrowdStrike 的 Falcon Sensor 应用程序连接到组织&#xff0c;并且遇到蓝屏死机 &#xff0…

JavaScript:节流与防抖

目录 一、前言 二、节流&#xff08;Throttle&#xff09; 1、定义 2、使用场景 3、实现原理 4、代码示例 5、封装节流函数 三、防抖&#xff08;Debounce&#xff09; 1、定义 2、使用场景 3、实现原理 4、代码示例 5、封装防抖函数 四、异同点总结 一、前言 …