当前位置: 首页 > news >正文

Single Image Haze Removal Using Dark Channel Prior(暗通道先验)

去雾算法都会依赖于很强的先验以及假设,并结合相应的物理模型,完成去雾过程。本文作者何凯明及其团队通过大量的无雾图像和有雾图像,归纳总结出无雾图像在其对应的暗通道图像上具有极低的强度值(趋近于0),并结合如下公式:
在这里插入图片描述
求出透射率参数以及全球大气光值,进而轻松的求取无雾图像J。

1、暗通道先验是什么?

暗通道先验是基于户外的的无雾图像总结归纳的,发现的一个普遍存在的现象就是:在大多数的非天空的图像块中,至少有一个图像通道的一些像素值是非常低且接近于0的。作者使用J_dark来表示暗通道图像,具体的计算公式如下所示:
在这里插入图片描述
上述公式可以知道,对于无雾图像y,求取其三通道对应像素为的最小值,并使用一个固定大小(15*15)的块去取其中最小的值即为当前像素的暗通道值。

下图很明显的展示了有雾与无雾图像的暗通道图像的差异:对于有雾图像(不考虑天空),暗通道图像偏白,也就是其强度值比较高,而对于无雾图像,暗通道图像整体偏黑,也就是其强度值比较低。

在这里插入图片描述
按照暗通道的定义就可以很清楚的知道:
在这里插入图片描述
上述公式就是本文的精髓暗通道先验,就是这么一个普普通通的经验总结,但是没有人想到。
作者在发现这个先验以后,还去做了很多的验证工作,其中就包括:
(1)随机选取5000张landscape+cityscape场景的数据,在剪裁掉天空部分后,resize到最长边为500的图像,使用15*15的核区域去计算暗通道图像,统计其强度概率分布图、累积概率强度分布图、图像的强度分布图

在这里插入图片描述
得出的结论是:
1、We can see that about 75 percent of the pixels in the dark channels have zero values, and the intensity of 90 percent of the pixels is below 25
2、most dark channels have very low average intensity, showing that only a small portion of outdoor haze-free images deviate from our prior

2、使用暗通道先验进行去雾

2.1 估计透射参数t

假设全球大气光值A是一个常量,利用公式(1)进行归一化操作可得:
在这里插入图片描述
接着假设t在一个固定大小的块中是恒定值,并且在公式(7)的两边同时求取暗通道值:
在这里插入图片描述
对于无雾图像来说J趋近于0的:
在这里插入图片描述
因此可以得出:
在这里插入图片描述
通过上述几个公式联合求解可得:
在这里插入图片描述
这里有一个特殊的点是:作者之前在讲解暗通道先验的时候排除了天空的干扰问题,但是通过公式(11)可以知道,对于有雾的天空而言,I和大气光参数A基本一致,因此:
在这里插入图片描述
对于天空来说t->0,说明对于天空来说,因为距离无限远,反射率基本等于0是完全合理的。因此作者很优雅的处理了暗通道中的非天空数据,不用特意将天空数据裁剪完成后方才进行暗通道计算。

实际环境下,无论天气如何晴朗,都会存在一些颗粒和雾气,这种现象称为aerial perspective,如果我们直接移除雾气,会让去雾后的图像看起来非常不自然,因此需要保留一定的雾气,而这就导致反射率需要加一些补偿值:
在这里插入图片描述

2.2 估计大气光值A

作者依托于Tan的理论:有雾图像中最亮的像素点是最不透明的,这主要针对是阴霾而没有阳光的天气,在这种情况下,大气光是照明的唯一来源,因此每个通道的颜色场景亮度为:
在这里插入图片描述
同时公式(1)可以改写为:
在这里插入图片描述当图像中的像素处于无线远的位置时,最亮点的像素时最haze-opaque的,可近似为A。但是实际经验告诉我们不能忽略阳光,因此在考虑阳光照射的情况下,公式(18),(19)就需要改写为:
在这里插入图片描述在这里插入图片描述
因此,图像中最亮的像素点可以比大气光值A大,可能会出现在白色的小汽车或者白色建筑物上
在这里插入图片描述依据暗通道先验,有雾图像的暗通道图表征其雾浓度,因此可以通过有雾图像的暗通道图来检测物浓度最大的区域,进而去提升大气光值的估计。
最终的方法是:首先获取图像的暗通道图,接着获取暗通道图中top 0.1%的的最亮像素点,然后选取暗通道图最亮像素点所对应的原始图像强度值最大的值作为大气光值。

2.3 图像重建

在得到大气光值A以及相应的透射率参数t以后,可以利用22式进行求解并获取相应的无雾图像。
在这里插入图片描述

2.4 番外篇

由于透射参数t的求解比较粗暴,导致得到的t图比较粗糙,为了进行细腻处理,作者使用soft matting进行图像的refine,下图是对比:
在这里插入图片描述
Soft matting的效果明显比直接求出的t值好很多,但是有一个致命的缺点是速度比较慢,因此在2010年何凯明使用引导滤波(guided filter)进行加速。

3 代码实现

3.1暗通道图求解

暗通道图就是对图像的RGB三通道求取最小值,然后在用一个核去取最小值,当然简便的方法是构造一个核,直接使用腐蚀操作进行实现。

	def cal_Dark_Channel(im, width = 15):im_dark = np.min(im, axis = 2)border = int((width - 1) / 2)im_dark_1 = cv2.copyMakeBorder(im_dark, border, border, border, border, cv2.BORDER_DEFAULT)res = np.zeros(np.shape(im_dark))for i in range(res.shape[0]):for j in range(res.shape[1]):res[i][j] = np.min(im_dark_1[i: i + width, j: j + width]) return res

3.2 求解大气光值A

	#计算A参数, im为暗通道图像, img为原图def cal_Light_A(im, img):s_dict = {}for i in range(im.shape[0]):for j in range(im.shape[1]):s_dict[(i, j)] = im[i][j]s_dict = sorted(s_dict.items(), key = lambda x: x[1])   A = np.zeros((3, ))num = int(im.shape[0] * im.shape[1] * 0.001)for i in range(len(s_dict) - 1, len(s_dict) - num - 1, -1):X_Y = s_dict[i][0]A = np.maximum(A, img[X_Y[0], X_Y[1], :])return A

3.3 反射率参数t

	def cal_trans(A, img, w = 0.95):dark = cal_Dark_Channel(img / A)t = np.maximum(1 - w * dark, 0)return t

3.4 使用引导滤波进行优化t

	def Guided_filtering(t, img_gray, width, sigma = 0.0001):mean_I = np.zeros(np.shape(img_gray))cv2.boxFilter(img_gray, -1, (width, width), mean_I, (-1, -1), True, cv2.BORDER_DEFAULT)mean_t = np.zeros(np.shape(t))cv2.boxFilter(t, -1, (width, width), mean_t, (-1, -1), True, cv2.BORDER_DEFAULT)corr_I = np.zeros(np.shape(img_gray))cv2.boxFilter(img_gray * img_gray, -1, (width, width), corr_I, (-1, -1), True, cv2.BORDER_DEFAULT)corr_IT = np.zeros(np.shape(t))cv2.boxFilter(img_gray * t, -1, (width, width), corr_IT, (-1, -1), True, cv2.BORDER_DEFAULT)var_I = corr_I - mean_I * mean_Icov_IT = corr_IT - mean_I * mean_ta = cov_IT / (var_I + sigma)    b = mean_t - a * mean_Imean_a = np.zeros(np.shape(a))mean_b = np.zeros(np.shape(b))cv2.boxFilter(a, -1, (width, width), mean_a, (-1, -1), True, cv2.BORDER_DEFAULT)cv2.boxFilter(b, -1, (width, width), mean_b, (-1, -1), True, cv2.BORDER_DEFAULT)return mean_a * img_gray + mean_b

3.5 图像恢复

	def harz_Rec(A, img, t, t0 = 0.1):img_o = np.zeros(np.shape(img))img_o[:, :, 0] = (img[:, :, 0] - A[0]) / (np.maximum(t, t0)) + A[0]img_o[:, :, 1] = (img[:, :, 1] - A[1]) / (np.maximum(t, t0)) + A[1]img_o[:, :, 2] = (img[:, :, 2] - A[2]) / (np.maximum(t, t0)) + A[2]return img_o

参考文献

走出寂静岭!暗通道先验的python实现
https://github.com/vaeahc/Dark_Channel_Prior/blob/master/Dark_Channel_Prior.py

相关文章:

Single Image Haze Removal Using Dark Channel Prior(暗通道先验)

去雾算法都会依赖于很强的先验以及假设,并结合相应的物理模型,完成去雾过程。本文作者何凯明及其团队通过大量的无雾图像和有雾图像,归纳总结出无雾图像在其对应的暗通道图像上具有极低的强度值(趋近于0),并…...

力扣382.链表随机节点(java利用数组随机返回节点值)

Problem: 382. 链表随机节点 文章目录 思路解题方法复杂度Code 思路 注意链表与数组的特性,对于随机访问读取的操作利用数组可以较方便实现,所以我们可以将链表中的节点值先存入到数组中最后再取出随机生成节点位置的值。 解题方法 1.生成List集合与Rand…...

在jupyter中使用R

如果想在Jupyter Notebook中使用R语言,以下几个步骤操作可行: 1、启动Anaconda Prompt 2、进入R的安装位置,切换到R的安装位置:D:\Program Files\R\R-3.4.3\bin,启动R,具体代码操作步骤如下,在…...

2023(第四届)江西开放数据创新应用大赛等你来挑战!

邀请函 这是一个友好的邀请。无论你是数据领域的专家、学生还是爱好者,我们都欢迎你加入这个平台。这不仅仅是一场比赛,更是一个交流、学习和展示自己的机会。 丰厚奖金:我们为参赛者准备了总计15W的奖金池,期待你的才华在这里得…...

2023-mac rz sz 安装

之前安装过一次,没问题,这次按照之前教程装了就不管上传下载都会卡住; step1: brew install lrzsz step2:在/usr/local/bin 路径下配置两个sh,之前从网上找到的直接用都不对,下面这个是调试过的正式可用的 iterm2…...

使用Matplotlib绘画3D图时运行不出结果,也不报错,图片是空白 !!

1.问题: 我使用如下代码运用matplotlib中的Axes3D绘画3D图,但是运行出来的结果是空白。 import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D #导入3D包 fig plt.figure() #窗口 #ax Axes3D(fig) # X, Y …...

Matlab函数——find

介绍 当你需要返回某个数组中符合指定条件的所有元素的索引时,可以使用 MATLAB 中的 find 函数。 find 函数语法: indices find(X) indices find(X, k) indices find(X, k, first) indices find(X, k, last) 其中,X 是一个数组&#xf…...

mac安装python3

文章目录 1. 安装1.1 brew安装(失败)2. 下载安装包 2. 查看版本3. 配置 1. 安装 1.1 brew安装(失败) brew install python3下载完成后报错:Error: python3.10: unknown or unsupported macOS version: :dunno 解决&a…...

【星海出品】VUE(一)

Windows安装nvm控制器 Windows里找都PowerShell。右击点击管理员运行。 1.安装choco Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString(https://chocolatey.org/install.ps1))2.安装NVM choco install nvm 3.查看可…...

Stable Diffusion 的提示词使用技巧

推荐Stable Diffusion自动纹理工具: DreamTexture.js自动纹理化开发包 什么是提示语? 提示语是人工智能中的一个重要组成部分,尤其是自然语言处理 (NLP)。在AI自人工智能中,想要获得好的效果,简…...

Hook函数

在嵌入式系统中,hook函数(也被称为钩子函数)是一种特殊类型的函数,它会在特定的事件发生时被操作系统内部调用。例如,在实时操作系统(RTOS)中,如果删除了一个任务,就会调…...

USB简介系列-01

文章目录 USB简介一、电气USB简介 通用串行总线(USB)是由Compaq,Intel,Microsoft和NEC开发的规范,后来惠普,朗讯和飞利浦加入。这些公司成立了 USB Implementers Forum, Inc 作为一家非营利性公司,以发布规范并组织 USB 的进一步开发。 USB-IF的目的是为当时使用的PC…...

算法小白的心得笔记:比较小数点后五位,而不会受到浮点数精度问题的影响。

epsilon 来比较浮点数 double epsilon 1e-6; // for 6 decimal places for (const auto &ratio : colorRatio) {std::cout << "__" << inum << "__" << ratio << " ";if ((inum - 1) % 10 0){std::cout &l…...

11月起,33个省份纳入数电票开票试点范围内,发票无纸化已是大势所趋!

10月底&#xff0c;北京、贵州、山东&#xff08;不含青岛市&#xff09;、湖南、宁夏5个地区相继发布开展数电票试点工作的通知&#xff0c;至此&#xff0c;全国已有33个省份纳入数电票开票试点范围内。根据上述5地区发布的相关公告&#xff0c;11月1日将正式推行“数电票”开…...

NLP之Bert多分类实现案例(数据获取与处理)

文章目录 1. 代码解读1.1 代码展示1.2 流程介绍1.3 debug的方式逐行介绍 3. 知识点 1. 代码解读 1.1 代码展示 import json import numpy as np from tqdm import tqdmbert_model "bert-base-chinese"from transformers import AutoTokenizertokenizer AutoToken…...

matlab中的mapminmax函数初步理解和应用

matlab中的mapminmax函数初步认识 一、mapminmax 顾名思义&#xff1a;映射最大最小 二、语法及举例 2.1 语法1 [Y,PS] mapminmax(X) 将矩阵X映射形成矩阵Y, Y中每行中的最小值对应-1&#xff0c;最大值对应1。PS是一个包含映射信息的结构体。 举例&#xff1a; clc cle…...

svc和ingress的关系

在Kubernetes中&#xff0c;SVC有三种类型&#xff0c;分别是ClusterIP、NodePort和LoadBalancer。而Ingress则是一种服务类型的扩展&#xff0c;它主要用于处理HTTP和HTTPS流量&#xff0c;并提供了对集群内部服务的路由和负载均衡功能。 下面简要介绍SVC的三种类型和Ingress…...

可以使用以下代码对数据库查询结果进行分组统计

public static void GroupAndStatistic(string connectionString, string query) {// 创建一个SQLSugar实例var db new SQLSugarClient(connectionString);// 使用QueryHelper类执行查询var dataTable db.Query<DataRow>().From(query).ExecuteDataTable();// 使用LINQ…...

win10提示mfc100u.dll丢失的解决方法,快速解决dll问题

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“mfc100u.dll丢失”。那么&#xff0c;mfc100u.dll是什么&#xff1f;mfc100u.dll是Microsoft Visual C Redistributable文件之一&#xff0c;它包含了用于MFC (Microsoft Foundation Class…...

zookeeper:启动原理

主类&#xff1a; QuorumPeerMain, 其中调用了main对象的initializeAndRun方法&#xff0c; 首先定义了QuorumPeerConfig对象&#xff0c;然后调用了parse方法&#xff0c;parse方法代码如下&#xff1a; 其中调用的parseProperties方法的代码如下&#xff1a; 可以看到&am…...

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…...

dedecms 织梦自定义表单留言增加ajax验证码功能

增加ajax功能模块&#xff0c;用户不点击提交按钮&#xff0c;只要输入框失去焦点&#xff0c;就会提前提示验证码是否正确。 一&#xff0c;模板上增加验证码 <input name"vdcode"id"vdcode" placeholder"请输入验证码" type"text&quo…...

智能在线客服平台:数字化时代企业连接用户的 AI 中枢

随着互联网技术的飞速发展&#xff0c;消费者期望能够随时随地与企业进行交流。在线客服平台作为连接企业与客户的重要桥梁&#xff0c;不仅优化了客户体验&#xff0c;还提升了企业的服务效率和市场竞争力。本文将探讨在线客服平台的重要性、技术进展、实际应用&#xff0c;并…...

Java - Mysql数据类型对应

Mysql数据类型java数据类型备注整型INT/INTEGERint / java.lang.Integer–BIGINTlong/java.lang.Long–––浮点型FLOATfloat/java.lang.FloatDOUBLEdouble/java.lang.Double–DECIMAL/NUMERICjava.math.BigDecimal字符串型CHARjava.lang.String固定长度字符串VARCHARjava.lang…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

Vue2 第一节_Vue2上手_插值表达式{{}}_访问数据和修改数据_Vue开发者工具

文章目录 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染2. 插值表达式{{}}3. 访问数据和修改数据4. vue响应式5. Vue开发者工具--方便调试 1.Vue2上手-如何创建一个Vue实例,进行初始化渲染 准备容器引包创建Vue实例 new Vue()指定配置项 ->渲染数据 准备一个容器,例如: …...

cf2117E

原题链接&#xff1a;https://codeforces.com/contest/2117/problem/E 题目背景&#xff1a; 给定两个数组a,b&#xff0c;可以执行多次以下操作&#xff1a;选择 i (1 < i < n - 1)&#xff0c;并设置 或&#xff0c;也可以在执行上述操作前执行一次删除任意 和 。求…...

在WSL2的Ubuntu镜像中安装Docker

Docker官网链接: https://docs.docker.com/engine/install/ubuntu/ 1、运行以下命令卸载所有冲突的软件包&#xff1a; for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt-get remove $pkg; done2、设置Docker…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...