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

深度图的方法实现加雾,Synscapes数据集以及D455相机拍摄为例

前言

在次之前,我们已经做了图像加雾的一些研究,这里我们将从深度图的方法实现加雾展开细讲

图像加雾算法的研究与应用_图像加雾 算法-CSDN博客

接下来将要介绍如何使用深度图像生成雾效图像的方法。利用Synscapes数据集,通过读取EXR格式的深度信息,结合摄像机参数和暗通道先验等技术,计算传输图和大气光照强度,并应用朗伯-比尔定律生成雾效图像。文中提供了完整的代码示例,包括从深度图读取数据、计算传输图和大气光、以及生成和保存雾效图像。此外,还介绍了如何使用自制数据集进行处理。该方法适用于自动驾驶数据增强、增强现实和图像去雾等领域,并提供了详细的注释和参考资料,帮助读者更好地理解和实现图像加雾技术。 

Synscapes数据集

下载路径:Synscapes data set (liu.se)

这个数据集很大,全部下载完成后才能解压。

从exr文件读取深度信息并进行可视化的方法在上一次已经讲过,所以不在赘述:图像加雾算法的研究与应用_图像加雾,具体在第5部分给出。

原作者使用的是matlab版本的:sakaridis/fog_simulation-SFSU_synthetic (github.com)

# utils.pyimport json
import numpy as np
from skimage.color import rgb2gray
from skimage.morphology import square, erosiondef camera_parameters(camera_parameters_file):"""相机参数从 JSON 文件中读取相机参数。:param camera_parameters_file:存储摄像机参数的 JSON 文件的完整路径。:return:f_x (float): 标量,类型为 float,对应于 x 轴的焦距参数(包含纵横比),单位为像素。c_x (float): 标量,类型为 float,对应于 x 轴的光学中心,单位为像素。c_y (float): 标量,类型为 float,对应于 y 轴的光学中心,单位为像素。"""with open(camera_parameters_file, 'r') as file:camera_parameters = json.load(file)f_x = camera_parameters['camera']['intrinsic']['fx']c_x = camera_parameters['camera']['intrinsic']['u0']c_y = camera_parameters['camera']['intrinsic']['v0']return f_x, c_x, c_ydef distance_in_meters(depth_map_in_meters, camera_parameters_file):"""以米为单位的距离使用密集深度图和摄像机固有参数作为输入,以与图像相同分辨率的密集图计算空气厚度,即被描绘物体与摄像机中心的距离,以米为单位。:param depth_map_in_meters: 深度图,以米为单位。:param camera_parameters_file: 相机参数文件。:return: 与深度图相同大小的距离图,以米为单位。"""f_x, c_x, c_y = camera_parameters(camera_parameters_file)height, width = depth_map_in_meters.shape    #创建一个与深度图像大小相同的网格,以便后续计算距离X, Y = np.meshgrid(np.arange(1, width + 1), np.arange(1, height + 1))# 深度图像中的像素值(通常是相机到物体的距离)转换为实际距离,以米为单位distance_map_in_meters = depth_map_in_meters * np.sqrt((f_x ** 2 + (X - c_x) ** 2 + (Y - c_y) ** 2) / f_x ** 2)return distance_map_in_metersdef brightest_pixels_count_rf(number_of_pixels, brightest_pixels_fraction):"""计算最亮像素的数量:param number_of_pixels: 图片中的像素数量:param brightest_pixels_fraction: 最亮像素分数:return: 最亮像素的数量"""brightest_pixels_count_tmp = int(brightest_pixels_fraction * number_of_pixels)brightest_pixels_count = brightest_pixels_count_tmp + ((brightest_pixels_count_tmp + 1) % 2)return brightest_pixels_countdef estimate_atmospheric_light_rf(I_dark, I):"""估计大气光照强度根据输入图像暗通道中最亮像素的一部分来估算大气光,如《图像去噪学习框架中的雾霾相关特征研究》中所建议。:param I_dark: 暗通道的灰度图像。:param I:      与 I_dark 高度和宽度相同的彩色图像。:return:        L (numpy.ndarray): 1x1x3 矩阵,包含大气光值估算值。index_L (int): 单通道版本图像中与大气光等值的像素的线性指数。"""brightest_pixels_fraction = 1 / 1000  #最亮像素分数height, width = I_dark.shapenumber_of_pixels = height * widthbrightest_pixels_count = brightest_pixels_count_rf(number_of_pixels, brightest_pixels_fraction)# 识别暗通道中最亮像素的指数。I_dark_vector = I_dark.flatten()indices = np.argsort(I_dark_vector)[::-1]  # 按降序排序brightest_pixels_indices = indices[:brightest_pixels_count]# 计算原始图像中暗部亮像素的灰度强度。I_gray_vector = rgb2gray(I).flatten()I_gray_vector_brightest_pixels = I_gray_vector[brightest_pixels_indices]# 从原始图像中灰度强度中值最亮的像素中找出能产生大气光的像素下标。median_intensity = np.median(I_gray_vector_brightest_pixels)index_median_intensity = np.where(I_gray_vector_brightest_pixels == median_intensity)[0][0]index_L = brightest_pixels_indices[index_median_intensity]row_L, column_L = np.unravel_index(index_L, (height, width))L = I[row_L, column_L]return Ldef get_dark_channel(I, neighborhood_size = 15):"""获取暗色通道使用侵蚀法计算输入图像相对于正方形邻域斑块的暗色通道。:param I: 输入彩色或灰度图像。:param neighborhood_size: 用于侵蚀的正方形斑块的边长,单位为像素。:return:    I_dark (numpy.ndarray): 输出与 I 相同类型、高度和宽度的灰度图像。I_eroded (numpy.ndarray): 与 I 尺寸相同的中间侵蚀图像。"""# 设置邻域大小# neighborhood_size = 15# 创建方形结构元素se_single_channel = square(neighborhood_size)# 将结构元素在每个通道上重复三次se = np.stack([se_single_channel] * 3, axis=-1)  #用来定义一个矩形区域,用于后续的图像形态学操作。I_eroded = erosion(I, se)                        #侵蚀是形态学操作之一,它用结构元素扫描图像,并将图像中的每个像素值替换为其邻域内像素值的最小值。I_dark = np.min(I_eroded, axis=2)                #获取每个像素在第三个维度(通常是颜色通道)上的最小值。这样做可能是为了将图像从彩色转换为灰度,因为对于灰度图像来说,每个像素只有一个值,即灰度值。return I_darkdef haze_linear(R, t, L_atm):"""使用与朗伯-比尔定律相对应的线性灰度模型,从干净图像生成灰度图像。:param R: H×W×image_channels 表示场景真实辐射度的干净图像。:param t: H×W 传输图。:param L: 1×1×image_channels 均质大气光。:return: 合成灰度图像,大小与输入的干净图像 R 相同。"""L_atm = L_atm.reshape(1, 1, 3)image_channels = L_atm.shape[2]                                        # 包含所有通道传输图副本的辅助矩阵,可方便地表达灰度图像。t_replicated = np.repeat(t[:, :, np.newaxis], image_channels, axis=2)  # 将一个灰度图像的雾度值扩展到所有颜色通道上I = t_replicated * R + (1 - t_replicated) * L_atmreturn Idef transmission_homogeneous_medium(d, beta, camera_parameters_file):"""根据比尔-朗伯定律,利用给定的深度图计算透射图。区分场景深度 d 和摄像机与每个像素所描绘物体之间的距离 l。:param d: H×W 矩阵,包含处理后图像的深度值(以米为单位)。:param beta: 衰减系数(以米为单位)。常数,因为介质是均质的。:param camera_parameters_file: 相机参数文件。:return: H×W 矩阵,介质传输值范围为 [0,1]。"""l = distance_in_meters(d, camera_parameters_file)t = np.exp(-beta * l)return tif __name__=="__main__":camera_parameters_file = r"D:\PythonProject\MB_TaylorFormer\RShazy\FoggySynscapes\data\demo\camera\camera.json"f_x, c_x, c_y = camera_parameters(camera_parameters_file)print(f_x, c_x, c_y)

详细解析请看中文注解

这里请按照默认下载的目录进行,不要随意做修改,相机的内参请自己创建,在数据集的json文件中已经给出。

import os
import numpy as np
from PIL import Image
from skimage.io import imread
import matplotlib.pyplot as plt
from RShazy.FoggySynscapes.utils import get_dark_channel, transmission_homogeneous_medium
from RShazy.FoggySynscapes.utils import estimate_atmospheric_light_rf, haze_linear
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = 'Times New Roman'
from pyzjr.data import multi_makedirs
from RShazy.FoggySynscapes.depth_utils import read_depth_from_exrdef demo_test(demo_root_dir, iter, beta = 0.06, window_size = 15):depth_exr_path = os.path.join(demo_root_dir, 'depth')camera_json_file = os.path.join(demo_root_dir, 'camera.json')image_rgb_path = os.path.join(demo_root_dir, 'rgb')depth_image = read_depth_from_exr(os.path.join(depth_exr_path, f"{iter}.exr"))img_uint8 = imread(os.path.join(image_rgb_path, f'{iter}.png'))clear_image = img_uint8.astype(float) / 255.0t = transmission_homogeneous_medium(depth_image, beta, camera_json_file)clear_image_dark_channel = get_dark_channel(clear_image, window_size)L_atm = estimate_atmospheric_light_rf(clear_image_dark_channel, clear_image)I = haze_linear(clear_image, t, L_atm)converted_I = (I * 255).astype(np.uint8)pil_I = Image.fromarray(converted_I)return pil_Iif __name__=="__main__":import matplotlib# import pyzjrmatplotlib.use('TkAgg')demo_root_dir = r"F:\dataset\Dehazy\synscapes\Synscapes\img"foggy_result_dir = r"D:\PythonProject\MB_TaylorFormer\RShazy\FoggySynscapes\Synscapes\test/hazy"multi_makedirs(foggy_result_dir)# _, length = pyzjr.get_file_list(os.path.join(demo_root_dir, "rgb"))# print(length)  # 25000for i in range(251, 352):pil_I = demo_test(demo_root_dir, i)# plt.imshow(pil_I)# plt.show()print(f"{i} 已保存图片到",os.path.join(foggy_result_dir, f"{i}.png"))pil_I.save(os.path.join(foggy_result_dir, f"{i}.png"))

合成效果如下所示:

D455相机拍摄自制数据集

拍摄以及无效区域处理方法请看此文:D455相机RGB与深度图像对齐,缓解相机无效区域的问题

这里我们需要修改读取深度图的方式:

import numpy as npdef read_depth_from_npy(npy_file_path):"""读取指定的NPY文件中的深度信息"""depth_data = np.load(npy_file_path)return depth_data

记得将自己拍摄rgb图像和处理过后的depth文件进行替换

目录结构请按照下面的方式进行:

D455相机的参数:

{
  "camera": {
    "intrinsic": {
      "fx": 387.3067321777344,
      "fy": 387.3067321777344,
      "resx": 640,
      "resy": 480,
      "u0": 321.67352294921875,
      "v0": 237.27777099609375
    }
  }
}

import os
import numpy as np
from PIL import Image
from skimage.io import imread
import matplotlib.pyplot as plt
from RShazy.FoggySynscapes.utils import get_dark_channel, transmission_homogeneous_medium
from RShazy.FoggySynscapes.utils import estimate_atmospheric_light_rf, haze_linear
plt.rcParams['font.family'] = 'serif'
plt.rcParams['font.serif'] = 'Times New Roman'
from RShazy.FoggySynscapes.depth_utils import read_depth_from_exr, read_depth_from_npydef demo_test(demo_root_dir, iter, beta = 0.06, window_size = 15):depth_exr_path = os.path.join(demo_root_dir, 'depth')camera_json_file = os.path.join(demo_root_dir, 'camera.json')image_rgb_path = os.path.join(demo_root_dir, 'rgb')depth_image = read_depth_from_npy(os.path.join(depth_exr_path, f"{iter}.npy"))img_uint8 = imread(os.path.join(image_rgb_path, f'{iter}.png'))clear_image = img_uint8.astype(float) / 255.0t = transmission_homogeneous_medium(depth_image, beta, camera_json_file)clear_image_dark_channel = get_dark_channel(clear_image, window_size)L_atm = estimate_atmospheric_light_rf(clear_image_dark_channel, clear_image)I = haze_linear(clear_image, t, L_atm)converted_I = (I * 255).astype(np.uint8)pil_I = Image.fromarray(converted_I)return pil_Iif __name__=="__main__":import matplotlibmatplotlib.use('TkAgg')demo_root_dir = r"D:\PythonProject\MB_TaylorFormer\RShazy\FoggySynscapes\datas\img"foggy_result_dir = r"D:\PythonProject\MB_TaylorFormer\RShazy\FoggySynscapes\outputs/hazy"os.makedirs(foggy_result_dir, exist_ok=True)# _, length = pyzjr.get_file_list(os.path.join(demo_root_dir, "rgb"))# print(length)  # 25000for i in range(1, 5):pil_I = demo_test(demo_root_dir, i, beta = 0.2)# plt.imshow(pil_I)# plt.show()print(f"{i} 已保存图片到",os.path.join(foggy_result_dir, f"{i}.png"))pil_I.save(os.path.join(foggy_result_dir, f"{i}.png"))

室外场景: 

室内场景:

 

参考文章

完善后的根据深度图加雾代码Python_图像加雾python-CSDN博客

【python】通过深度图生成雾图(HAZERD)_深度图像信息合成雾-CSDN博客

图片合成雾的方法概述_图像加雾-CSDN博客

MATLAB实现利用图像深度信息合成不同浓度的雾【Cityscapes_foggy数据集】_自己合成带雾数据集-CSDN博客

相关文章:

深度图的方法实现加雾,Synscapes数据集以及D455相机拍摄为例

前言 在次之前,我们已经做了图像加雾的一些研究,这里我们将从深度图的方法实现加雾展开细讲 图像加雾算法的研究与应用_图像加雾 算法-CSDN博客 接下来将要介绍如何使用深度图像生成雾效图像的方法。利用Synscapes数据集,通过读取EXR格式的…...

QT: 读写ini配置文件(实现qml界面登录,修改)

目录 一.功能介绍 二.暴露属性 三.指定INI文件的路径和格式。 四.登录操作 1.检查INI文件中是否含有登录信息; 2.读取存储的ID; 3.读取存储的密码; 4.成功返回1;失败返回2; 五.修改账号 1.检查INI文件中是否含有登录信…...

DevOps 安全集成:从开发到部署,全生命周期安全守护

目录 一、DevOps 安全集成:为什么要做? 二、DevOps 安全集成:如何做? 三、DevOps 安全集成的优势 四、DevOps 安全集成:一些最佳实践 五、DevOps 安全集成:未来展望 六、思考与建议 七、总结 DevOps…...

R语言数据分析15-xgboost模型预测

XGBoost模型预测的主要大致思路: 1. 数据准备 首先,需要准备数据。这包括数据的读取、预处理和分割。数据应该包括特征和目标变量。 步骤: 读取数据:从CSV文件或其他数据源读取数据。数据清理:处理缺失值、异常值等…...

重构大学数学基础_week04_从点积理解傅里叶变换

这周我们来看一下傅里叶变换。傅里叶变换是一种在数学和许多科学领域中广泛应用的分析方法,它允许我们将信号或函数从其原始域(通常是时间域或空间域)转换到频域表示。在频域中,信号被表示为其组成频率的幅度和相位,这…...

Shell以及Shell编程

Shell的任务 ①分析命令; ②处理通配符、变量替换、命令替换、重定向、管道和作业控制; ③搜索命令并执行。 内部命令:内嵌在Shell中。 外部命令:存在于磁盘上的独立可执行文件。 #!/bin/bash #! 称为一个幻数&…...

从记忆到想象:探索AI的智能未来

引言 人工智能(AI)在信息处理、数据分析和任务自动化等方面展现了强大的能力。然而,在人类独有的记忆和想象力领域,AI仍然有很长的路要走。加利福尼亚大学戴维斯分校的心理学和神经科学教授查兰兰加纳特(Charan Ranga…...

“安全生产月”专题报道:AI智能监控技术如何助力安全生产

今年6月是第23个全国“安全生产月”,6月16日为全国“安全宣传咨询日”。今年全国“安全生产月”活动主题为“人人讲安全、个个会应急——畅通生命通道”。近日,国务院安委会办公室、应急管理部对开展好2024年全国“安全生产月”活动作出安排部署。 随着科…...

【转】ES, 广告索引

思考: 1)直接把别名切换到上一个版本索引 --解决问题 2)广告层级索引如何解决? -routing、join 3)查询的过程:query and fetch, 优化掉fetch 4)segment合并策略 5)全量写入时副…...

Unity学习要点

前言 学习Unity作为游戏开发的强大工具,对于初学者来说,掌握一些基础而实用的技巧是非常重要的。这不仅能帮助你更快地上手,还能在项目开发过程中提高效率。以下是一些Unity初学者的使用技巧,希望能为你的学习之旅提供帮助。 ##…...

简单使用phpqrcode 生成二维码图片

$path ROOT_PATH; //tp项目根路径 require_once $path.vendor/phpqrcode/phpqrcode.php; //加载phpqrcode库 $url http://.$_SERVER[HTTP_HOST]./home/index/detail?id.$param[id]; $value $url; //二维码内容 $errorCorrectionLevel L; //容错级别 $mat…...

软考架构-计算机网络考点

会超纲,3-5分 网络分类 按分布范围划分 局域网 LAN 10m-1000m左右 房间、楼宇、校园 传输速率高 城域网 MAN 10km 城市 广域网 WAN 100km以上 国家或全球(英特网) 按拓扑结构划分 总线型:利用率低、干…...

渗透测试之内核安全系列课程:Rootkit技术初探(三)

今天,我们来讲一下内核安全! 本文章仅提供学习,切勿将其用于不法手段! 目前,在渗透测试领域,主要分为了两个发展方向,分别为Web攻防领域和PWN(二进制安全)攻防领域。在…...

大模型日报2024-06-08

大模型日报 2024-06-08 大模型资讯 AI研究:通过消除矩阵乘法实现高效的大语言模型 摘要: 该AI研究探讨了通过消除矩阵乘法来实现高效且可扩展的大语言模型(LLMs)。此方法旨在提升模型性能,提供更快速和高效的计算方案。 AWS大力投…...

leetcode 1631.最小体力消耗路径

思路:BFS二分 这道题和洛谷上的那个“汽车拉力赛”那道题很相似,但是这道题相较于洛谷那个来说会简单一些。 这里作者一开始写的时候思路堵在了怎么在BFS中用二分,先入为主的以为需要先写出来搜索函数然后再去处理二分的事,但是…...

【ARM64 常见汇编指令学习 19.2 -- ARM64 地址加载指令 ADR 详细介绍】

文章目录 地址加载指令 ADRADR 指令使用场景例子注意事项 地址加载指令 ADR ARMv8 架构引入了一系列的改进和扩展,包括对汇编指令集的更新。在这之中,ADR 指令是一个重要的组成部分,它用于计算并加载一个地址到寄存器。 ADR 指令 ADR 指令…...

vscode输出控制台中文显示乱码最有效解决办法

当VSCode的输出控制台中文显示乱码时,一个有效的解决办法是通过设置环境变量来确保编码的正确性。以下是解决方式: 首先,设置环境变量以修正乱码问题: 如果上述方法没有解决乱码问题,请继续以下步骤: 右键…...

springboot + Vue前后端项目(第十五记)

项目实战第十五记 写在前面1.后端接口实现1.1 用户表添加角色字段1.2 角色表增加唯一标识字段1.3 UserDTO1.4 UserServiceImpl1.5 MenuServiceImpl 2. 前端实现2.1 User.vue2.2 动态菜单设计2.2.1 Login.vue2.2.2 Aside.vue 2.3 动态路由设计2.3.1 菜单表新增字段page_path2.3.…...

如何在Windows 11中恢复丢失的快速访问菜单?这里提供解决办法

序言 在电脑的“快速访问”菜单中找不到固定的项目?或者,整个菜单对你来说已经消失了吗?无论哪种方式,你都可以强制你的电脑恢复菜单并显示其中的所有项目。以下是如何在你的Windows 11电脑上做到这一点。 将文件资源管理器设置为打开到主页 当你在文件资源管理器的左侧…...

变声器软件免费版有哪些?国内外12大热门变声器大盘点!(新)

变声软件是一种人工智能AI音频处理工具,允许用户实时修改自己的声音或改变预先录制的音频。这些软件解决方案可提供不同的效果,如改变声音的音调或速度,或将我们的声音转换成其他人或其他东西的声音,如名人、卡通人物、机器人或不…...

从零实现富文本编辑器#5-编辑器选区模型的状态结构表达

先前我们总结了浏览器选区模型的交互策略,并且实现了基本的选区操作,还调研了自绘选区的实现。那么相对的,我们还需要设计编辑器的选区表达,也可以称为模型选区。编辑器中应用变更时的操作范围,就是以模型选区为基准来…...

第一篇:Agent2Agent (A2A) 协议——协作式人工智能的黎明

AI 领域的快速发展正在催生一个新时代,智能代理(agents)不再是孤立的个体,而是能够像一个数字团队一样协作。然而,当前 AI 生态系统的碎片化阻碍了这一愿景的实现,导致了“AI 巴别塔问题”——不同代理之间…...

k8s业务程序联调工具-KtConnect

概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...

06 Deep learning神经网络编程基础 激活函数 --吴恩达

深度学习激活函数详解 一、核心作用 引入非线性:使神经网络可学习复杂模式控制输出范围:如Sigmoid将输出限制在(0,1)梯度传递:影响反向传播的稳定性二、常见类型及数学表达 Sigmoid σ ( x ) = 1 1 +...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量,这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

深度学习水论文:mamba+图像增强

🧀当前视觉领域对高效长序列建模需求激增,对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模,以及动态计算优势,在图像质量提升和细节恢复方面有难以替代的作用。 🧀因此短时间内,就有不…...

scikit-learn机器学习

# 同时添加如下代码, 这样每次环境(kernel)启动的时候只要运行下方代码即可: # Also add the following code, # so that every time the environment (kernel) starts, # just run the following code: import sys sys.path.append(/home/aistudio/external-libraries)机…...

Caliper 负载(Workload)详细解析

Caliper 负载(Workload)详细解析 负载(Workload)是 Caliper 性能测试的核心部分,它定义了测试期间要执行的具体合约调用行为和交易模式。下面我将全面深入地讲解负载的各个方面。 一、负载模块基本结构 一个典型的负载模块(如 workload.js)包含以下基本结构: use strict;/…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...

DAY 26 函数专题1

函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...