C#,保持亮度的动态直方图均衡化(Brightness Preserving Dynamic Histogram Equalization:BPDHE)源代码

 

图像增强的主要目的是显示隐藏的图像细节,或者用新的动态范围增加图像对比度。直方图均衡(HE)是用于图像对比度增强的最流行的技术之一,因为HE在计算上快速且易于实现。HE通过基于输入灰度级的概率分布重新映射图像的灰度级来执行其操作。然而,HE很少用于视频监控、数码相机和电视等消费电子应用,因为HE往往会引入一些令人讨厌的伪影和不自然的增强,包括强度饱和效应。这个问题的原因之一是HE通常会显著改变图像的亮度,从而使输出图像变得饱和,具有非常亮或暗的强度值。因此,为了增强消费电子产品的图像,亮度保持是需要考虑的一个重要特性。

为了克服HE的局限性并保持图像的亮度,人们提出了几种保持亮度的直方图均衡技术。首先,Kim提出了保持亮度的双直方图均衡(BBHE),BBHE根据输入图像的平均值将输入图像直方图分为两部分,然后独立地对每个部分进行均衡。因此,由于保留了原始平均亮度,所以保留了平均亮度。Wan等人引入了二元子图像直方图均衡(DSIHE),它类似于BBHE,只是输入图像的中值用于直方图分割,而不是平均亮度[5]。Chen和Ramli提出了最小平均亮度误差双直方图均衡(MMBEBHE),这是BBHE方法的扩展,提供了最大的亮度保持。该算法找出原始图像和增强图像之间的最小平均亮度误差。它采用最优点作为分离点,而不是输入图像的平均值或中值。尽管这些方法可以执行良好的对比度增强,但根据直方图中灰度分布的变化,它们也会导致更令人讨厌的副作用。递归平均分离HE(RMSHE)是BBHE的另一个改进版本。该方法递归地将直方图分离为多个子直方图,而不是像BBHE中那样将两个子直方图分离。最初,根据原始直方图的平均亮度创建两个子直方图。随后,来自先前获得的两个子直方图的平均亮度被用作创建更多子直方图的第二和第三分离点。以类似的方式,递归地执行该算法,直到满足所需数量的子直方图。然后,HE方法独立地应用于每个子直方图。前面讨论的方法是基于通过使用中值或平均亮度将原始直方图划分为几个子直方图。尽管上述方法很好地保持了平均亮度,但这些方法不能进一步扩展位于动态范围的最小值或最大值附近的亚直方图区域。然而,它也并非没有副作用,例如褪色的外观、不希望的棋盘效果和图像亮度的显著变化。

为了解决上述问题,Abdullah Al-Wadud等人引入了动态直方图均衡(DHE)技术。DHE基于局部极小值对原始直方图进行分割。然而,DHE并不考虑亮度的保持。为此,Ibrahim和Kong提出了保持亮度的动态直方图均衡(BPDHE)。该方法基于平滑直方图的局部最大值来分割图像直方图。它为每个分区分配一个新的动态范围。最后,对输出强度进行归一化,使所得图像的平均强度等于输入强度。尽管BPHE在平均亮度保持方面表现良好,但亮度归一化的比率起着重要作用。较小的比值会导致不显著的对比度增强。对于大比率(即比率值大于1),最终强度值可能超过输出动态范围的最大强度值。超出的像素将被量化为灰度级的最大强度值,并产生强度饱和问题(在MATLAB环境中)。Sheet等人提出了保持亮度的动态模糊直方图均衡(BPDFHE)。这是BPDFHE的增强版本。BPDFHE技术以这样的方式操纵图像直方图,即不发生直方图峰值的重新映射,而只发生两个连续峰值之间的谷部分中的灰度值的重新分布。使用BPDFHE方法的结果显示出良好的对比度增强和小的伪影。

为了克服不必要的过度增强和噪声放大,提出了基于模糊逻辑的灰度和彩色图像直方图均衡技术。所提出的FHE方法不仅保持了图像的亮度,而且提高了原始图像的局部对比度。首先,利用模糊集理论计算模糊直方图。其次,根据原始图像的中值将模糊直方图一分为二。最后,HE方法被独立地应用于每个子直方图以提高对比度。

using System;
using System.Text;
using System.Collections;
using System.Collections.Generic;

namespace Legal.Truffer.ImageProcess

{

public partial static class CVUtility
{

    /// <summary>
    /// 直方图均衡化
    /// 保持亮度的动态直方图均衡化(Brightness Preserving Dynamic Histogram Equalization:BPDHE)
    /// </summary>
    /// <param name="src"></param>
    /// <returns></returns>
    public static Mat Equalization_BPDHE(Mat src)
    {
        double[] B = new double[256];
        for (int k = 0; k < 255; k++)
        {
            int t1 = 0, t2 = 0, t3 = 0;
            for (int m = 0; m < src.Rows; m++)
            {
                for (int n = 0; n < src.Cols; n++)
                {
                    if (src.At<Vec3b>(m, n)[0] == k) t1 = t1 + 1;
                    if (src.At<Vec3b>(m, n)[1] == k) t2 = t2 + 1;
                    if (src.At<Vec3b>(m, n)[2] == k) t3 = t3 + 1;
                }
            }

            int t = t1 + t2 + t3;
            double b = 1.0f / (src.Rows * src.Cols * 3.0);
            double x = t * b;
            B[k] = x;
        }

        double[] T1 = new double[256];
        for (int i = 1; i < 256; i++)
        {
            for (int j = 1; j < i; j++)
            {
                T1[i - 1] = B[j - 1] + T1[i - 1];
            }
        }

        double[] T2 = new double[256];
        for (int i = 1; i < 256; i++)
        {
            T2[i - 1] = Math.Round((T1[i - 1] * 255) + 0.5);
        }

        Mat bpdhe = new Mat();
        src.CopyTo(bpdhe);
        for (int i = 0; i < 255; i++)
        {
            for (int j = 0; j < src.Rows; j++)
            {
                for (int k = 0; k < src.Cols; k++)
                {
                    if (bpdhe.At<Vec3b>(j, k)[0] == i)
                        bpdhe.At<Vec3b>(j, k)[0] = (byte)T2[i];
                    if (bpdhe.At<Vec3b>(j, k)[1] == i)
                        bpdhe.At<Vec3b>(j, k)[1] = (byte)T2[i];
                    if (bpdhe.At<Vec3b>(j, k)[2] == i)
                        bpdhe.At<Vec3b>(j, k)[2] = (byte)T2[i];
                }
            }
        }

        return bpdhe;
    }
}

}

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

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

相关文章

微服务远程调用openFeign整合

✅作者简介&#xff1a;大家好&#xff0c;我是Cisyam&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Cisyam-Shark的博客 &#x1f49e;当前专栏&#xff1a; 微服务探索之旅 ✨特色专…

聚类分析(文末送书)

目录 聚类分析是什么 一、 定义和数据类型 聚类应用 聚类分析方法的性能指标 聚类分析中常用数据结构有数据矩阵和相异度矩阵 聚类分析方法分类 二、K-means聚类算法 划分聚类方法对数据集进行聚类时包含三个要点 K-Means算法流程: K-means聚类算法的特点 三、k-med…

【数据挖掘】时间序列模型处理指南(二)

一、说明 本文是一个系列文章的第二部分&#xff0c;本文将用股票数据进行时间序列分析为例&#xff0c;对时间分析的方法、过程&#xff0c;进行详细阐述。 二、前文章节 在文章第一部分种&#xff1a;【数据挖掘】时间序列模型处理&#xff08;一&#xff09;_无水先生的博客…

C++ 文件和流

我们已经使用了 iostream 标准库&#xff0c;它提供了 cin 和 cout 方法分别用于从标准输入读取流和向标准输出写入流。 本教程介绍如何从文件读取流和向文件写入流。这就需要用到 C 中另一个标准库 fstream&#xff0c;它定义了三个新的数据类型&#xff1a; 数据类型描述of…

Java之Javac、JIT、AOT之间的关系

Javac&#xff1a;javac 是java语言编程编译器。全称java compiler。但这时候还是不能直接执行的&#xff0c;因为机器只能读懂汇编&#xff0c;也就是二进制&#xff0c;因此还需要进一步把.class文件编译成二进制文件。 Java的执行过程 详细流程 结论&#xff1a;javac编译后…

【ESP32C3合宙ESP32C3】:ESP32C3和合宙ESP32C3的环境搭建与离线包安装

项目场景&#xff1a; 最近买了一块合宙ESP32C3的开发板&#xff0c;于是想要开发一下&#xff0c;当然开发最开始少不掉开发环境的搭建&#xff0c;在这个搭建的过程中&#xff0c;遇到了一些问题&#xff0c;解决了&#xff0c;也希望能帮助到大家。 ESP32C3 和 合宙ES…

gnutls_handshake() failed: The TLS connection was non-properly terminated.

从远程仓库获取所有更新&#xff0c;并保存在本地时&#xff0c;使用git fetch 命令时出现如下错误&#xff1a; 解决办法&#xff1a; 问题解决&#xff1a; 参考资料 拉取github报错 gnutls_handshake() failed: The TLS connection was non-properly terminated. git获取…

Laravel 多字段去重count计数

Laravel 多字段去重count计数 背景&#xff1a;需要统计数据列表总条数&#xff08;字段1、字段2去重统计&#xff09; table&#xff1a;policy_view,去重字段admin_id和permission 期望结果&#xff1a;count不含重复统计数据 解决思路&#xff1a; 语法&#xff1a;DISTI…

SpringMVC 学习整理

文章目录 一、SpringMVC 简介1.1 什么是MVC1.2 什么是Spring MVC1.3 Spring MVC的特点 二、SpringMVC 快速入门三、RequestMapping注解说明四、SpringMVC获取请求参数4.1 通过ServletAPI获取请求参数4.2 通过控制器方法的形参获取请求参数4.3 通过RequestParam接收请求参数4.4 …

Python工具箱系列(三十七)

二进制文件操作&#xff08;上&#xff09; python比较擅长与文本相关的操作。但现实世界中&#xff0c;对于非文本消息的处理也很普遍。例如&#xff1a; ◆通过有线、无线传递传感器获得的测量数据。 ◆卫星通过电磁波发送测量数据。 ◆数据中心的数万台服务器发送当前CP…

【Python】Python进阶系列教程--Python AI 绘画(二十)

文章目录 前言Windows 环境安装Civitai 介绍 前言 往期回顾&#xff1a; Python进阶系列教程-- Python3 正则表达式&#xff08;一&#xff09;Python进阶系列教程-- Python3 CGI编程&#xff08;二&#xff09;Python进阶系列教程-- Python3 MySQL - mysql-connector 驱动&a…

【单片机】STM32F103C8T6单片机,OLED 1.3寸 IIC OLED,STM32F103单片机,I2C OLED

文章目录 main.coled.coled.hOLED_Font.h 效果&#xff1a; main.c #include "sys.h" #include "usart.h" #include "OLED.h"int main(void) {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2); /* 设置NVIC中断分组2:2位抢占优…