pytorch实现DCP暗通道先验去雾算法及其onnx导出

pytorch实现DCP暗通道先验去雾算法及其onnx导出

  • 简介
  • 实现
  • ONNX导出
    • 导出
    • 测试

简介

最近在做图像去雾,于是在Pytorch上复现了一下dcp算法。暗通道先验去雾算法是大神何恺明2009年发表在CVPR上的一篇论文,还获得了当年的CVPR最佳论文。
dcp算法效果

实现

具体原理就不阐述了,网上的解析多的是,这里直接把用pytorch复现的代码贴出来:

import torchdef dcp(img, omega=0.75):h, w = img.shape[2:]imsz = h * w# 要查找的是暗通道中前0.1%的值numpx = torch.clamp_min(imsz // 1000, 1)# 找到暗通道的索引,弄成[batch, 3, numpx],因为要匹配三个通道,所以需要expanddark = torch.min(img, dim=1, keepdim=True)[0]indices = torch.topk(dark.view(-1, imsz), k=numpx, dim=1)[1].view(-1, 1, numpx).expand(-1, 3, -1)# 用上述索引匹配原图中的3个通道,并求其平均值a = (torch.gather(img.view(-1, 3, imsz), 2, indices).sum(2) / numpx).view(-1, 3, 1, 1)# 代公式算txtx =  1 - omega * torch.min(img / a.view(-1, 3, 1, 1), dim=1, keepdim=True)[0]# 代公式算jxreturn (img - a) / torch.clamp_min(tx, 0.1) + a

函数有两个参数:

  1. img:经归一化后的(N,C,H,W)布局的图像
  2. omega:DCP算法的一个参数ω,数值越大效果越强

如果想在模型训练时引入dcp算法,可以用nn.Module封装一下:

class DCP(torch.nn.Module):def __init__(self, omega):self._omega = omegadef forward(self, x):return dcp(x, self._omega)

ONNX导出

导出

既然能封装成Module,那么就顺便试了一下导出ONNX。
导出onnx需要安装onnx和onnxsim:

pip install onnx onnxsim

导出代码如下:

import torch
import onnx
from onnxsim import simplify def dcp(img, omega=0.75):h, w = img.shape[2:]imsz = h * w# 要查找的是暗通道中前0.1%的值numpx = torch.clamp_min(imsz // 1000, 1)# 找到暗通道的索引,弄成[batch, 3, numpx],因为要匹配三个通道,所以需要expanddark = torch.min(img, dim=1, keepdim=True)[0]indices = torch.topk(dark.view(-1, imsz), k=numpx, dim=1)[1].view(-1, 1, numpx).expand(-1, 3, -1)# 用上述索引匹配原图中的3个通道,并求其平均值a = (torch.gather(img.view(-1, 3, imsz), 2, indices).sum(2) / numpx).view(-1, 3, 1, 1)# 代公式算txtx =  1 - omega * torch.min(img / a.view(-1, 3, 1, 1), dim=1, keepdim=True)[0]# 代公式算jxreturn (img - a) / torch.clamp_min(tx, 0.1) + aclass DCPExport(torch.nn.Module):def forward(self, x, omega):return dcp(x, omega)def export(output='dcp.onnx'):torch.onnx.export(DCPExport(), (torch.randn(1, 3, 255, 255, dtype=torch.float32), torch.tensor(0.75, dtype=torch.float32)), 'dcp.onnx', input_names=['fog_image', 'omega'], output_names=['clear_image'], dynamic_axes={'fog_image': {0: 'batch', 2: 'height', 3: 'width'},'clear_image': {0: 'batch', 2: 'height', 3: 'width'},})onnx_model = onnx.load(output) model_simp, check = simplify(onnx_model) assert check, "简化模型失败" onnx.save(model_simp, output) if __name__ == '__main__':export()

导出结果如下:

onnx
导出后的onnx输入输出如下:

  • 输入:
    1. fog_image[float32]:形状为NCHW,且归一化的有雾图像,其中通道数C必须为3
    2. omega[float32]:dcp的参数,类型为浮点数
  • 输出:
    1. clear_image[float32]:形状为NCHW,且归一化的无雾图像,其中通道数C为3

下载链接:https://pan.baidu.com/s/1A1jSJQBFCGTeM8vbHOrysQ?pwd=tl6p

测试

用cv2和pil都可以:

import numpy as np
import cv2
from PIL import Image
from onnxruntime import InferenceSessionmodel = InferenceSession('dcp.onnx')# CV2读图
image = cv2.imread('dehaze/dehaze/input/images/indoor1.jpg')
# 这里说明一下,因为dcp对所有通道进行同等变换,所以不用bgr和rgb互转了,出来的结果都是一样的
# x = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
x = np.transpose(image, (2, 0, 1))[None].astype(np.float32) / 255.
res = model.run(['clear_image'], {'fog_image': x, 'omega': np.array(0.75, dtype=np.float32)})[0][0]
res = np.transpose(res, (1, 2, 0))
res = np.clip(res*255+0.5, 0, 255).astype(np.uint8)
# res = cv2.cvtColor(res, cv2.COLOR_RGB2BGR)
cv2.imwrite('onnx-cv.png', np.concatenate((image, res), 1))# PIL读图
image = Image.open('dehaze/dehaze/input/images/indoor1.jpg')
x = np.transpose(image, (2, 0, 1))[None].astype(np.float32) / 255.
res = model.run(None, {'fog_image': x, 'omega': np.array(0.75, dtype=np.float32)})[0][0]
res = np.transpose(res, (1, 2, 0))
res = np.clip(res*255+0.5, 0, 255).astype(np.uint8)
Image.fromarray(np.concatenate((image, res), 1)).save('onnx-pil.png')

效果:

onnx效果

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

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

相关文章

软件测试项目测试报告总结

测试计划概念:就在软件测试工作实施之前明确测试对象,并且通过资源、时间、风险、测试范围和预算等方面的综合分析和规划,保证有效的实施软件测试。 需求挖掘的6个方面: 1、输入方面 2、处理方面 3、结果输出方面 4、性能需求…

HAOS如何添加小米设备

环境: Home Assistant 11.2 Xiaomi Miot Auto 0.7.14 问题描述: HAOS如何添加小米设备 解决方案: 1.通过 HACS 自动安装 打开 Home Assistant 的 HACS 页面 2.搜索小米 3.在新打开的页面中找到Xiaomi MIoT,下载安装 下载 …

掌握pip的基本命令和高级用法:轻松管理Python包

掌握pip的基本命令和高级用法 一、简介二、安装和配置pip三、基本命令和用法3.1、安装和卸载包3.2、包管理3.3、包依赖管理3.4、虚拟环境管理 四、高级用法4.1、自定义pip的配置4.2、使用requirements.txt文件管理项目依赖4.3、创建和发布自己的Python包4.4、使用pip下载非Pyth…

【✅Java中有了基本类型为什么还需要包装类?】

✅Java中有了基本类型为什么还需要包装类? ✅Java中有了基本类型为什么还需要包装类✅Java的8中基本数据类型 ✅知识拓展✅基本类型和包装类型的区别✅如何理解自动拆装箱?✅拆箱与装箱✅自动拆装箱✅自动拆装箱原理 ✅哪些地方会自动拆装箱?…

条款6:若不想使用编译器自动生成的函数,就该明确拒绝

有些场景我们不需要编译器默认实现的构造函数,拷贝构造函数,赋值函数,这时候我们应该明确的告诉编译器,我们不需要,一个可行的方法是将拷贝构造函数和赋值函数声明为private。 class HomeForSale { ... }; HomeForSal…

linux、widnows的免费局域网桌面远程工具之NoMachine

统信UOS、银河麒麟及其他的linux桌面系统/windows系统都可进行远程桌面操作使用。 1.先到官网下载https://downloads.nomachine.com/自己使用的软件版本。 2.首先下载windwos端的的版本64位进行安装,安装是先暂时退出windows的杀毒软件,以免提示你各种确…

Clonable 接口和深拷贝

Object 类中存在一个 clone 方法, 调用这个方法可以创建一个对象的 “拷贝”. 想用clone方法时报错了,查看一下: clone方法被protected修饰.不同包只能在子类中访问,可以用super关键字访问clone方法返回类型是Object,所以需要向下转型CloneNotSupportedException是受查异常…

FormData文件上传多文件上传

一、简介 ​ 通常情况下,前端在使用post请求提交数据的时候,请求都是采用application/json 或 application/x-www-form-urlencoded编码类型,分别是借助JSON字符串来传递参数或者keyvalue格式字符串(多参数通过&进行连接&#…

React 中的 ref 和 refs:解锁更多可能性(上)

🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…

算法分析与设计课后练习29

给定集合S{3, 7, 5, 9}, C 20, 近似参数 ε0.2, 写出 近似算法求解子集和问题的过程。

ThinkPad E550c

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么?二、使用步骤 1.引入库2.读入数据总结 前言 提示:这里可以添加本文要记录的大概内容: 例如:…

喜讯丨思码逸正式加入北京信创工委会!

近日,经北京信息化协会信息技术应用创新工作委员会(以下简称“北京信创工委会”)投票表决,研发效能行业领先者北京思码逸科技有限公司(简称:思码逸)正式加入“北京信创工委会”,成为…