边缘检测——PidiNet网络训练自己数据集并优化推理测试(详细图文教程)

PiDiNet 是一种用于边缘检测的算法,它提出了一种简单、轻量级但有效的架构。PiDiNet 采用了新

颖的像素差卷积,将传统的边缘检测算子集成到现代 CNN 中流行的卷积运算中,以增强任务性能。

在 BSDS500、NYUD 和 Multicue 上进行了大量的实验,以证明其有效性、高训练和推理效率。

一、源码包

我自己在官网源码包的基础上改过一些代码,我提供的源码包中新增了网络裁剪优化,CPU推理测试代码,边缘检测图与原图融合等代码,也包含了训练集,推荐学者下载我提供的源码包使用。

官网地址:PidiNet

我提供的源码包下载链接:网盘链接,提取码:kmxb

论文地址:论文

我提供的源码包解压后的样子如下:

在这里插入图片描述

二、数据集准备

增强的数据集有BSD 500、PASCAL VOC和NYUD,下载链接见下,直接将链接复制到迅雷里面下载,速度很快。在我提供的源码包中有BSD 500数据集,位于目录pidinet\path\to中,如下:

在这里插入图片描述

有自己制作好数据集的,直接导入使用。

BSD 500数据集下载链接:   http://mftp.mmcheng.net/liuyun/rcf/data/HED-BSDS.tar.gz
PASCAL VOC数据集下载链接: http://mftp.mmcheng.net/liuyun/rcf/data/PASCAL.tar.gz
NYUD数据集下载链接  http://mftp.mmcheng.net/liuyun/rcf/data/NYUD.tar.gz

在这里插入图片描述

三、训练

有多种可以选择,官网提供的如下:

在这里插入图片描述

其中效果最好的是table7_pidinet,最轻量化的是table5_pidinet-tiny-l,学者根据自己需求选择模型大小,上图像的各个模型权重文件在源码包中trained_models文件夹下,可以直接用这些权重文件测试。

在这里插入图片描述

3.1 训练和测试命令

下面是各个模型对应的训练和测试命令:

############### Table 5, Baseline 
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet --config baseline --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_baseline --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_baseline.pth

# generate maps (no need to convert because baseline is already a vanilla cnn)
python main.py --model pidinet --config baseline --sa --dil -j 4 --gpu 0 --savedir /path/to/table5_baseline --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_baseline.pth

# 101 FPS
python throughput.py --model pidinet --config baseline --sa --dil -j 1 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet --config carv4 --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet.pth

# generate maps with converted pidinet
python main.py --model pidinet_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir /path/to/table5_pidinet --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet.pth --evaluate-converted

# 96 FPS
python throughput.py --model pidinet_converted --config carv4 --sa --dil -j 1 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet-L
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet --config carv4 --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet-l --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet-l.pth

# generate maps with converted pidinet
python main.py --model pidinet_converted --config carv4  -j 4 --gpu 0 --savedir /path/to/table5_pidinet-l --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet-l.pth --evaluate-converted

# 135 FPS
python throughput.py --model pidinet_converted --config carv4 -j 1 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet-small
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet_small --config carv4 --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet-small --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet-small.pth

# generate maps with converted pidinet
python main.py --model pidinet_small_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir /path/to/table5_pidinet-small --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet-small.pth --evaluate-converted

# 161 FPS
python throughput.py --model pidinet_small_converted --sa --dil --config carv4 -j 1 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet-small-l
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet_small --config carv4 --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet-small-l --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet-small-l.pth

# generate maps with converted pidinet
python main.py --model pidinet_small_converted --config carv4 -j 4 --gpu 0 --savedir /path/to/table5_pidinet-small-l --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet-small-l.pth --evaluate-converted

# 225 FPS
python throughput.py --model pidinet_small_converted --config carv4 -j 2 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet-tiny
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet_tiny --config carv4 --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet-tiny --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet-tiny.pth

# generate maps with converted pidinet
python main.py --model pidinet_tiny_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir /path/to/table5_pidinet-tiny --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet-tiny.pth --evaluate-converted

# 182 FPS 
python throughput.py --model pidinet_tiny_converted --sa --dil --config carv4 -j 2 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 5, PiDiNet-tiny-l
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet_tiny --config carv4 --resume --iter-size 24 -j 4 --gpu 0 --epochs 20 --lr 0.005 --lr-type multistep --lr-steps 10-16 --wd 1e-4 --savedir /path/to/table5_pidinet-tiny-l --datadir /path/to/BSDS500 --dataset BSDS #--evaluate /path/to/table5_pidinet-tiny-l.pth

# generate maps with converted pidinet
python main.py --model pidinet_tiny_converted --config carv4 -j 4 --gpu 0 --savedir /path/to/table5_pidinet-tiny-l --datadir /path/to/BSDS500 --dataset BSDS --evaluate /path/to/table5_pidinet-tiny-l.pth --evaluate-converted

# 253 FPS
python throughput.py --model pidinet_tiny_converted --config carv4 -j 2 --gpu 0 --datadir /path/to/BSDS500 --dataset BSDS



############### Table 6, PiDiNet
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet --config carv4 --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 14 --lr 0.005 --lr-type multistep --lr-steps 8-12 --wd 1e-4 --savedir /path/to/table6_pidinet --datadir /path/to/NYUD --dataset NYUD-image --lmbda 1.3 #--evaluate /path/to/table6_pidinet.pth

# generate maps with converted pidinet
python main.py --model pidinet_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir /path/to/table6_pidinet --datadir /path/to/NYUD --dataset NYUD-image --lmbda 1.3 --evaluate /path/to/table6_pidinet.pth --evaluate-converted

# 66 FPS
python throughput.py --model pidinet_converted --sa --dil --config carv4 -j 1 --gpu 0 --datadir /path/to/NYUD --dataset NYUD-image



############### Table 7, PiDiNet
# train, or generate maps without conversion (uncomment the --evaluate)
python main.py --model pidinet --config carv4 --sa --dil --resume --iter-size 24 -j 4 --gpu 0 --epochs 14 --lr 0.005 --lr-type multistep --lr-steps 8-12 --wd 1e-4 --savedir /path/to/table7_pidinet --datadir /path/to/Multicue/multicue_v2 --dataset Multicue-boundary-1 #--evaluate /path/to/table7_pidinet.pth

# generate maps with converted pidinet
python main.py --model pidinet_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir /path/to/table7_pidinet --datadir /path/to/Multicue/multicue_v2 --dataset Multicue-boundary-1 --evaluate /path/to/table7_pidinet.pth --evaluate-converted

# 17 FPS
python throughput.py --model pidinet_converted --sa --dil --config carv4 -j 1 --gpu 0 --datadir /path/to/Multicue/multicue_v2 --dataset Multicue-boundary-1

各个模型的定义,在代码中的位置如下:

在这里插入图片描述

实际训练使用,只需要将修改训练命令中模型保存路径:–savedir;数据集路径:–dataset

具体使用如下,在终端输入命令,下面就是训练过程:

在这里插入图片描述

3.1 模型保存

训练好的模型会自动保存指定路径下:

在这里插入图片描述

四、测试

各个模型对应的测试命令见上面3.1。

在我提供的源码包中,单独区分了GPU测试脚本和CPU测试脚本,如下:

在这里插入图片描述
使
用测试命令时要修改读入测试集的路径:–datadir;保存测试结果的路径:–savedir;训练好的模型权重路径:–evaluate。其它的参数可以根据情况调整。

GPU测试命令例子如下:

python main_GPU.py --model pidinet_converted --config carv4 --sa --dil -j 4 --gpu 0 --savedir ./path/to/savedir_table7_pidinet --datadir ./path/to/custom_images --dataset Custom --evaluate ./trained_models/table5_baseline.pth --evaluate-converted

CPU测试命令例子如下:

python main_CPU.py --model pidinet_tiny_converted_small5 --config carv4 --sa --dil -j 4 --savedir ./results/pidinet_tiny_small5_Crop --datadir ./path/to/custom_images --dataset Custom --evaluate ./path/to/Train_Models/pidinet_tiny_small5_Crop/save_models/checkpoint_008.pth --evaluate-converted

下面是终端中输入命令实际测试的过程:

在这里插入图片描述

最终的测试结果会自动保存在–savedir指定的路径中,如下:

在这里插入图片描述

4.1 测试结果

4.1.1 测试场景1

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

4.1.2 测试场景2

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

4.1.3 测试场景3

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

4.2 检测边缘与原图融合

融合方法是先单独在Y通道上对原图和边缘图进行叠加融合,最后用融合后的Y通道和原图图的Cr,Cb合并,再转为BGR图像。用这样的融合方法得到的图像比较自然,色彩信息不会丢失。

4.2.1 融合代码

# 此方法可行,在Y通道上将图像的细节融合后再与CrCb色彩通道合并颜色

import cv2
import numpy as np

# 读取原始图像

image = cv2.imread('path/to/DenoiseImages/23.jpg', cv2.IMREAD_COLOR)    # 原图

image_edge = cv2.imread("results/Table_pidinet_tiny_l/eval_results/imgs_epoch_019/23.png")  # 边缘图像

# 转YCrCb图像
image_YCrCb = cv2.cvtColor(image,cv2.COLOR_BGR2YCrCb)
image_edge_YCrCb = cv2.cvtColor(image_edge,cv2.COLOR_BGR2YCrCb)

# 拆分YCRCb图像各个通道

image_y,image_cr,image_cb = cv2.split(image_YCrCb)

image_edge_y,image_edge_cr,image_edge_cb = cv2.split(image_edge_YCrCb)

# 将边缘图像转换为彩色图像
# edge_image_color = cv2.cvtColor(image_edge, cv2.COLOR_GRAY2BGR)

# 将边缘图像叠加到原始图像上
enhanced_image_y = cv2.addWeighted(image_y, 0.9, image_edge_y, 0.1, 0)

# 合同通道
fusion_YCrCb = cv2.merge((enhanced_image_y,image_cr,image_cb))

# YCrCb转BGR
fusion_BGR = cv2.cvtColor(fusion_YCrCb,cv2.COLOR_YCrCb2BGR)

cv2.imwrite("results/DenoiseImages+Table_pidinet_tiny_l/23.bmp",fusion_BGR)

# fusion_RGB = cv2.cvtColor(fusion_YCrCb,cv2.COLOR_YCrCb2RGB)

# 显示增强后的图像
cv2.imshow("original",image)
cv2.imshow("image_edge",image_edge)
cv2.imshow('image_y',image_y)
cv2.imshow('image_edge_y',image_edge_y)
cv2.imshow('enhanced_image_y',enhanced_image_y)
cv2.imshow('Fusion Image', fusion_BGR)
cv2.waitKey(0)
cv2.destroyAllWindows()

4.2.2 融合结果展示

4.2.1 场景1

在这里插入图片描述

4.2.2 场景2

在这里插入图片描述

五、模型优化

官网已经提供了多种模型,但是在CPU上还是远远不够,所以我的优化主要是针对速度。

5.1 修改通道数和空洞率

我最小的通道数为5,空洞率为2。其它值也可以设置,检测效果会有影响。

在这里插入图片描述

5.2 裁剪卷积层

我裁剪网络结构的部分如下图红框所示,裁剪代码脚本为源码包中的pidinet_Crop.py文件。

在这里插入图片描述
对应的源码里面将block_3部分和block_4部分删除,同时forword里面也要对应修改,如下:

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

通过这种方法能够提升一定速度,但是检测效果差了很多。

六、推理速度

我自己测试的图像分辨率为480*360,电脑处理器:12th Gen Intel® Core™ i7-12700H 2.30 GHz。

官网table7_pidinet模型大小为2.73M。 CPU推理速度:450ms/fps,GPU推理速度:4ms/fps。

官网table5-pidinet-tiny-l模型大小为304K。CPU推理速度:143.6ms/fps,GPU推理速度:2ms/fps。

模型优化,裁剪通道数为5,空洞率为2,模型大小为:178K。 CPU推理速度:81ms/fps。

模型优化,卷积层裁剪部分如下图红框所示,通道数为5,空洞率为2,模型大小为:65.06K。CPU推理速度:72.25ms/fps。

总结

以上就是边缘检测算法PidiNet网络训练自己数据集并优化推理测试的详细图文教程,该网络架构都是采用轻量化的模块集成,确实快,但依然有优化空间,有更深入研究的学者欢迎一起探讨。

总结不易,多多支持,谢谢!

猜你喜欢

转载自blog.csdn.net/qq_40280673/article/details/135267158