【变化检测】基于HANet建筑物(LEVIR-CD)变化检测实战及ONNX推理

主要内容如下:

1、LEVIR-CD数据集介绍及下载
2、运行环境安装
3、HANet模型训练与预测
4、Onnx运行及可视化

运行环境:Python=3.8,torch1.12.0+cu113,onnxruntime=1.19.2【这里装CPU版,GPU版低于1.19.2算子报错】
likyoo变化检测源码:https://github.com/likyoo/open-cd
使用情况:代码风格属于openmmlab那套,通过修改配置文件config进行模型选择和训练、环境配置简单、训练速度一般。
训练资源消耗:默认参数配置,且batch_size为8时,显存占用15G左右,RTX4080迭代40000大概3.5小时。
ONNX推理:RTX4080推理耗时约4s

1 LEVIR-CD数据集介绍

1.1 简介

LEVIR-CD 由 637 个超高分辨率(VHR,0.5m/像素)谷歌地球(GE)图像块对组成,大小为 1024 × 1024 像素。这些时间跨度为 5 到 14 年的双时态图像具有显着的土地利用变化,尤其是建筑增长。LEVIR-CD涵盖别墅住宅、高层公寓、小型车库、大型仓库等各类建筑。在这里,我们关注与建筑相关的变化,包括建筑增长(从土壤/草地/硬化地面或在建建筑到新的建筑区域的变化)和建筑衰退。这些双时态图像由遥感图像解释专家使用二进制标签(1 表示变化,0 表示不变)进行注释。我们数据集中的每个样本都由一个注释者进行注释,然后由另一个进行双重检查以生成高质量的注释。
数据来源:https://justchenhao.github.io/LEVIR/
论文地址:https://www.mdpi.com/2072-4292/12/10/1662
快速下载链接:https://aistudio.baidu.com/datasetdetail/104390/1

1.2 示例

在这里插入图片描述

2 运行环境安装

2.1 基础环境安装

【超详细】跑通YOLOv8之深度学习环境配置1-Anaconda安装
【超详细】跑通YOLOv8之深度学习环境配置2-CUDA安装

创建Python环境及换源可借鉴如下:
【超详细】跑通YOLOv8之深度学习环境配置3-YOLOv8安装

2.2 likyoo变化检测代码环境安装

2.2.1 代码下载

Git:git clone https://github.com/likyoo/open-cd.git
在这里插入图片描述

2.2.2 环境安装
# 1 创建环境
conda create -n likyoo python=3.8
conda activate likyoo# 2 安装torch
# 方式1:
conda install pytorch==1.12.0 torchvision==0.13.0 torchaudio==0.12.0 cudatoolkit=11.3 -c pytorch
# 方式2:
pip install torch==1.12.0+cu113 torchvision==0.13.0+cu113 torchaudio==0.12.0 --extra-index-url https://download.pytorch.org/whl/cu113# 3 验证torch安装是否为gpu版
import torch
print(torch.__version__)  # 打印torch版本
print(torch.cuda.is_available())  # True即为成功
print(torch.version.cuda)
print(torch.backends.cudnn.version())# 4 安装其他依赖库
cd ./open-cd-main# 4.1 安装 OpenMMLab 相关工具
pip install -U openmim
mim install mmengine
mim install "mmcv==2.0.0"
mim install "mmpretrain>=1.0.0rc7"  # (本地安装版本为1.2.0)
pip install "mmsegmentation==1.2.2"
pip install "mmdet==3.0.0"# 4.2 编译安装open-cd
pip install -v -e .# 5 可能缺少的库
pip install ftfy

3 HANet模型训练与预测

3.1 HANet模型介绍

3.1.1 简介


摘要:得益于深度学习技术的发展,基于自动特征提取的深度学习算法在变化检测(CD)任务上取得了显著的性能。然而,现有的基于深度学习的CD方法的性能受到已改变像素和未改变像素之间不平衡性的影响。为了解决这个问题,提出了一种基于不添加变化信息的渐进式前景平衡采样(PFBS)策略,帮助模型在早期训练过程中准确学习已改变像素的特征,从而提高检测性能。此外,我们设计了一种鉴别式孪生网络,层次化注意力网络(HANet),可以集成多尺度特征并细化详细特征。HANet的主要部分是HAN模块,这是一种轻量级且有效的自注意力机制。在两个具有极端不平衡标签的CD数据集上的广泛实验和消融研究验证了所提方法的有效性和效率。我们的模型可在以下网址获取:https://github.com/ChengxiHAN/HANet-CD。
论文地址:https://arxiv.org/pdf/2404.09178

3.1.2 模型结构

在这里插入图片描述
在这里插入图片描述

3.1.3 实验结果

在这里插入图片描述

3.2 模型训练与预测

3.2.1 修改训练配置文件

(1)选择训练配置
在这里插入图片描述

(2)修改configs\common\standard_256x256_40k_levircd.py
关键修改:输入数据集路径data_root一定要对!!!
batch_size和迭代数量等按自己需要调整,预测为1024大小。
在这里插入图片描述

3.2.2 模型训练与测试
# 训练,--config配置文件+保存文件夹名
python tools/train.py configs/hanet/hanet_256x256_40k_levircd.py --work-dir ./work_dirs/hanet# 测试==》得到评价指标
python tools/test.py configs/hanet/hanet_256x256_40k_levircd.py  ./work_dirs/hanet/iter_40000.pth
3.2.3 结果显示
# 测试==》得到结果图
python tools/test.py configs/hanet/hanet_256x256_40k_levircd.py  ./work_dirs/hanet/iter_40000.pth --show-dir tmp_infer

在这里插入图片描述

4 Onnx运行及可视化

4.1 Onnx导出静态和动态文件

(1)修改tools/export.py脚本,导出onnx,复制如下内容【修改了输入尺寸和增加一个动态onnx导出】:

# Copyright (c) Open-CD. All rights reserved.
import argparse
import loggingimport torch
from mmengine import Config
from mmengine.registry import MODELS, init_default_scopelogging.basicConfig(level=logging.INFO)
logger = logging.getLogger('opencd')def main(args):# must be called before using opencdinit_default_scope('opencd')config_path = args.configcheckpoint_path = args.checkpointinputs = args.inputsmodel_name = args.model_namemodel_name_dy = args.model_name_dyconfig = Config.fromfile(config_path, import_custom_modules=True)model = MODELS.build(config.model)ckpt = torch.load(checkpoint_path)state_dict = ckpt['state_dict']model.load_state_dict(state_dict, strict=True)model.eval()input_shape0 = tuple(map(int, inputs[0].split(',')))input_shape1 = tuple(map(int, inputs[1].split(',')))input0 = torch.rand(input_shape0)input1 = torch.rand(input_shape1)images = torch.concat((input0, input1), dim=1)# 导出静态onnxtorch.onnx.export(model,(images),model_name,input_names=['images'],output_names=['output'],verbose=False,opset_version=11,)# 导出动态onnxtorch.onnx.export(model,(images),model_name_dy,input_names=['images'],output_names=['output'],verbose=False,opset_version=11,dynamic_axes={"images": {0 :"batch_size", 2: "input_height", 3: "input_width"},"output": {0 :"batch_size", 2: "output_height", 3: "output_width"}})if __name__ == '__main__':parser = argparse.ArgumentParser()parser.add_argument('--config', '-c', type=str, default='')parser.add_argument('--checkpoint', '-m', type=str, default='')parser.add_argument('--inputs','-i',type=str,nargs='+',default=['1,3,1024,1024', '1,3,1024,1024'])parser.add_argument('--model-name', '-mn', type=str, default='model.onnx')parser.add_argument('--model-name_dy', '-mndy', type=str, default='model_dy.onnx')args = parser.parse_args()logger.info(args)main(args)

运行命令如下【结果生成两个onnx文件】:

python tools/export.py --config configs/hanet/hanet_256x256_40k_levircd.py --checkpoint ./work_dirs/hanet/iter_40000.pth

(2)查看模型结构
https://netron.app/
静态onnx
在这里插入图片描述
动态onnx
在这里插入图片描述
注意:其中的[1,6,1024,1024]表示两个[1,3,1024,1024]堆叠一起输入。

4.2 Onnx运行及可视化

4.2.1 Onnx推理运行

注意:由于LEVIR-CD图像为1024*1024大小,输入改成1024输入。

import os
import cv2
import time
import argparse
import numpy as np
import onnxruntime as ort  # 使用onnxruntime推理用上,pip install onnxruntime-gpu -i https://pypi.tuna.tsinghua.edu.cn/simpleclass CD(object):def __init__(self, onnx_model, in_shape=1024):self.in_shape = in_shape  # 图像输入尺度self.mean = [0.485, 0.456, 0.406]  # 定义均值和标准差(确保它们与图像数据的范围相匹配)  self.std = [0.229, 0.224, 0.225]  # 基于0-1范围的# 构建onnxruntime推理引擎self.ort_session = ort.InferenceSession(onnx_model,providers=['CUDAExecutionProvider', 'CPUExecutionProvider']if ort.get_device() == 'GPU' else ['CPUExecutionProvider'])# 归一化 def normalize(self, image, mean, std):  # 如果均值和标准差是基于0-255范围的图像计算的,那么需要先将图像转换为0-1范围  image = image / 255.0  image = image.astype(np.float32)  image_normalized = np.zeros_like(image)  for i in range(3):  # 对于 RGB 的每个通道  image_normalized[:, :, i] = (image[:, :, i] - mean[i]) / std[i]  return image_normalizeddef preprocess(self, img_a, img_b):# resize为1024大小if img_a.shape[0] != self.in_shape and img_a.shape[1] != self.in_shape:img_a = cv2.resize(img_a, (self.in_shape, self.in_shape), interpolation=cv2.INTER_LINEAR)if img_b.shape[0] != self.in_shape and img_b.shape[1] != self.in_shape:img_b = cv2.resize(img_b, (self.in_shape, self.in_shape), interpolation=cv2.INTER_LINEAR)# 应用归一化  img_a = self.normalize(img_a, self.mean, self.std)img_b = self.normalize(img_b, self.mean, self.std)img_a = np.ascontiguousarray(np.einsum('HWC->CHW', img_a)[::-1], dtype=np.single)  # (1024, 1024, 3)-->(3, 1024, 1024), BGR-->RGBimg_b = np.ascontiguousarray(np.einsum('HWC->CHW', img_b)[::-1], dtype=np.single)  # np.single 和 np.float32 是等价的img_a = img_a[None] if len(img_a.shape) == 3 else img_a  # (1, 3, 1024, 1024)img_b = img_b[None] if len(img_b.shape) == 3 else img_bconcat_img = np.concatenate((img_a, img_b), axis=1) return  concat_img# 推理def infer(self, img_a, img_b):concat_img = self.preprocess(img_a, img_b)  # (1024, 1024, 3)+(1024, 1024, 3) --> (1, 6, 1024, 1024)preds = self.ort_session.run(None, {self.ort_session.get_inputs()[0].name: concat_img})[0]  # (1, n, 1024, 1024) if preds.shape[1] == 1:out_img = (np.clip(preds[0][0], 0, 1) * 255).astype("uint8") else:out_img = (np.argmax(preds, axis=1)[0] * 255).astype("uint8")return out_imgif __name__ == '__main__':# Create an argument parser to handle command-line argumentsparser = argparse.ArgumentParser()parser.add_argument('--model', type=str, default='weights/model_dy.onnx', help='Path to ONNX model')parser.add_argument('--source_A', type=str, default=str('E:/datasets/LEVIR-CD/test/A/test_7.png'), help='A期图像')parser.add_argument('--source_B', type=str, default=str('E:/datasets/LEVIR-CD/test/B/test_7.png'), help='B期图像')parser.add_argument('--in_shape', type=int, default=1024, help='输入模型图像尺度')args = parser.parse_args()# 实例化变化检测模型cd= CD(args.model, args.in_shape)# Read image by OpenCVimg_a = cv2.imread(args.source_A)img_b = cv2.imread(args.source_B)# 推理+输出t1 = time.time()out = cd.infer(img_a, img_b)print('推理耗时:{}'.format(time.time() - t1))# 保存结果cv2.imwrite('./result/test_7_res.png', out)
4.2.2 结果可视化

显存:占用3G左右,推理速度:85ms左右(RTX4080)
在这里插入图片描述

4.2.3 进一步处理:

(1)可加入腐蚀膨胀处理,消除一些小白点等区域;
(2)将变化区域绘制在第二期图上,便于观察;

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

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

相关文章

一招解决微软copilot提示:该服务在您所在的地区不可用

随着windows 11的推出很多网友都开始注意到了微软copilot AI助手。科技快速发展当前AI已经是一个家喻户晓的名词了, 尤其是一些之前体验过ai强大功能的用户,对AI更加是爱不释手。虽然win 11 版本已经将copilot集成到系统当中,然后不少网友在想要体验时却…

kali里面搭建docker容器

注意事项:kali版本,镜像源 (1)权限为管理员: sudo su (2) 更新软件包列表并升级已安装的软件包 apt-get update apt-get upgrade 出错了,应该是更新源出问题了。 (3)更换镜像源&am…

stm32开发之串口空闲中断和环形数组的最简单的组合使用

前言 本次使用的是lwrb开源的源码;测试环境使用的是stm32f407zgt6这里不介绍lwrb的内容,如有需要请自行去查阅.这里会使用到rt_container_of的宏定义(相关介绍请参考rt_thread或linux源码相关的宏定义,其表达的内容是一致的)这里使用的是threadx做为os本…

Java调用数据库 笔记05

一. 数据库(通过各种驱动来实现调用): (应用程序通过接口控制的各种数据库驱动来调用数据库-->jdbc方法) 1.创建Java的普通class类 2.加载驱动 Class.forName("com.mysql.jdbc.Driver"); 3.驱动管理类…

TCP并发服务器的实现

一请求一线程 问题 当客户端数量较多时,使用单独线程为每个客户端处理请求可能导致系统资源的消耗过大和性能瓶颈。 资源消耗: 线程创建和管理开销:每个线程都有其创建和销毁的开销,特别是在高并发环境中,这种开销…

开源 AI 智能名片链动 2+1 模式 O2O 商城小程序在社群活动中的应用与时机选择

摘要:本文探讨了开源 AI 智能名片链动 21 模式 O2O 商城小程序在社群经济中的重要性,着重分析了如何借助该小程序适时举办大型活动以维持和引爆社群活跃度。通过对活动时机选择的研究,强调了针对社群用户量身定制活动时机的必要性&#xff0c…

简单了解微服务--黑马(在更)

认识微服务 单体架构 不适合大型复杂项目 微服务架构 将单体结构的各个功能模块拆分为多个独立的项目 拆取的独立项目分别开发,在部署的时候也要分别去编译打包,分别去部署,不同的模块部署在不同的服务器上,对外提供不同的功能…

渗透测试入门学习——php表单form与POST、GET请求练习

最终效果&#xff1a; 必填项为空报错提示&#xff1a; 代码&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><title>php表单练习</title> </head> <body> <?php//php中的…

UE5学习笔记22-武器瞄准和武器自动开火

0、一些疑问的记录 1.UUserWidget类和AHUD类的区别。两者都是关于界面显示的类。 实践&#xff1a; 想让界面和用户有交互使用UUserWidget&#xff0c;如果不要交互只是显示使用AHUD类&#xff0c;例如使用UUserWidget类制作开始界面&#xff0c;游戏开始&#xff0c;游戏设置&…

计算机人工智能前沿进展-大语言模型方向-2024-09-17

计算机人工智能前沿进展-大语言模型方向-2024-09-17 1. Large Language Models in Biomedical and Health Informatics: A Review with Bibliometric Analysis H Yu, L Fan, L Li, J Zhou, Z Ma, L Xian, W Hua, S He… - Journal of Healthcare …, 2024 生物医学和健康信息…

部分动态铜皮的孤岛无法删除。报错

(SPMHCI-1): Cannot break shape into fragments. 网上寻找了很多答案&#xff0c;都不太理想&#xff0c;不是我想要的方法。 终于功夫不负有心人&#xff0c;在Cadence官方论坛找到了蛛丝马迹。 Breaking Static shape into fragments - PCB Design - PCB Design & IC …

深入解析Transformer原理

在自然语言处理&#xff08;NLP&#xff09;领域&#xff0c;Transformer架构的出现无疑是一个里程碑式的进展。从Google的BERT到OpenAI的GPT系列&#xff0c;Transformer已经成为许多前沿AI模型的核心。今天&#xff0c;我们就来深入探讨Transformer的原理&#xff0c;帮助你更…

优惠充值话费api对接如何选择对接平台?

优惠充值话费接口通常由电信运营商、第三方支付平台或专业的充值服务提供商提供。这些平台通过API接口允许开发者将话费充值功能集成到应用程序或网站中。 选择哪个平台比较好&#xff0c;取决于以下几个因素&#xff1a; 覆盖范围&#xff1a;选择能够覆盖你需要服务的地区和…

深度学习-生成式检索-论文速读-2024-09-14

深度学习-生成式检索-论文速读-2024-09-14 前言: 生成式检索&#xff08;Generative Retrieval&#xff0c; GR&#xff09;是一种结合了生成模型和检索系统的人工智能技术方法。这种方法在处理信息检索任务时&#xff0c;不仅依赖于已有数据的检索&#xff0c;还能生成新的、…

c++基类和派生类对象的赋值转换——赋值兼容规则

1.引出 如下场景&#xff1a; 由于b是double类型&#xff0c;所以赋值给int类型的引用前&#xff0c;要先进行隐式类型转换&#xff0c;这中间会生成临时对象&#xff0c;类是对象具有常性&#xff0c;所以int&之前应该加上const。 但是下面的场景&#xff1a; 没有出现报…

Python3网络爬虫开发实战(16)分布式爬虫(第一版)

文章目录 一、分布式爬虫原理1.1 分布式爬虫架构1.2 维护爬取队列1.3 怎样来去重1.4 防止中断1.5 架构实现 二、Scrapy-Redis 源码解析2.1 获取源码2.2 爬取队列2.3 去重过滤2.4 调度器 三、Scrapy 分布式实现3.1 准备工作3.2 搭建 Redis 服务器3.3 部署代理池和 Cookies 池3.4…

python画图|中秋到了,尝试画个月亮(球体画法)

学习了一段时间的画图&#xff0c;已经掌握了一些3D图的画法&#xff0c;部分链接如下&#xff1a; python画图|极坐标下的3D surface-CSDN博客 python画图|3D参数化图形输出-CSDN博客 我们今天尝试一下月亮的画法。 【1】官网教程 首先还是到达官网教程学习&#xff1a; …

# 深度学习笔记(6)Hugginface -Transformer

深度学习笔记&#xff08;6&#xff09;Hugginface -Transformer 文章目录 深度学习笔记&#xff08;6&#xff09;Hugginface -Transformer一、工具包二、 Tokenizer三、 模型加载四、 输出五&#xff0c;padding的作用5.1 attention_mask5.2 不同padding方法 六&#xff0c;数…

基于yolov8+lprnet的中文车牌识别系统python源码+pytorch模型+精美GUI界面

【算法介绍】 基于YOLOv8和LPRNet的中文车牌识别系统是一种高效且准确的解决方案&#xff0c;结合了目标检测与字符识别的先进技术。YOLOv8作为最新的实时目标检测算法&#xff0c;以其高速度和精确度著称&#xff0c;能够迅速在图像或视频中定位车牌位置。LPRNet则是一种专为…

反向传播(Back Propagation,简称BP)

反向传播算法是用于训练神经网络的核心算法之一&#xff0c;它通过计算损失函数&#xff08;如均方误差或交叉熵&#xff09;相对于每个权重参数的梯度&#xff0c;来优化神经网络的权重。 1.前向传播&#xff08;Forward Propagation&#xff09; 步骤 输入层&#xff1a;接…