Faster-RCNN.pytorch的搭建、使用过程详解(适配PyTorch 1.0以上版本)

引言

本文主要介绍(1)如何跑通源代码;(2)配置过程中遇到的错误调试过程;(3)成功训练自己的数据集。

faster-rcnn pytorch代码下载

配置环境:

我复现代码的环境是python3.6+cuda10.1+Ubuntu16.04+Pytorch1.2。

强烈推荐使用 pytorch1.0.0版源码 进行配置,旧版本已不再维护,很多报错难以调试。

具体配置,此代码作者已在ReadMe中详细介绍,但鉴于初学者在复现中遇到的种种问题,下面将对“具体配置过程”做出进一步阐释,旨在做到浅显易懂,成功复现。

faster-rcnn pytorch配置过程

1. 安装torch

请移步至https://pytorch.org/get-started/locally/查看相应的安装命令,安装最新版的pytorch包。参考执行代码如下:

conda install pytorch==1.0.0 torchvision==0.2.1 cuda100 -c pytorch

2. 下载源码到本地

具体方法有以下两种:

(1)git clone 到本地

git clone -b pytorch-1.0 --single-branch --depth=1 --recursive https://github.com/jwyang/faster-rcnn.pytorch.git

其中:-b是分支名,--single-branch是clone指定分支的命令,--depth==1是指克隆最近一次更改,--recursive用于循环递归克隆子项目。

(2)直接下载zip文件至本地

在这里插入图片描述
强烈推荐第二种,简单、方便。

3. 创建数据文件夹

在本地创建一个文件夹专门用来搭建Faster-RCNN模型,所有的配置文件均在此目录下进行(如:“/detectron”)。

首先,将源码的zip文件copy至目标目录/detectron,同时解压缩得到如下所示文件夹;

在这里插入图片描述
其次,创建data文件夹,具体操作如下:

1. cd 进入project根目录
2. mkdir data   # 创建data文件夹

或者,直接执行

# && 表示前一条命令执行成功时,才执行后一条命令 ,如 echo '1‘ && echo '2' 
cd faster-rcnn.pytorch && mkdir data  # 一步实现上述2条命令,此处faster-rcnn.pytorch即为存放解压缩后源码的文件夹

4.下载数据至data文件夹

cd 进入data文件夹

开始下载压缩文件,执行如下命令,下载VOV2007标准数据集的相关数据

wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtrainval_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCtest_06-Nov-2007.tar
wget http://host.robots.ox.ac.uk/pascal/VOC/voc2007/VOCdevkit_08-Jun-2007.tar

执行下方命令解压缩数据到data/VOCdevkit

tar xvf VOCtrainval_06-Nov-2007.tar
tar xvf VOCtest_06-Nov-2007.tar
tar xvf VOCdevkit_08-Jun-2007.tar

cd 进入data文件夹下,创建软链接

ln -s VOCdevkit的绝对路径 VOCdevkit2007

完整的VOC2007数据集有三个压缩包:

  • VOCdevkit_08-Jun-2007.tar:开发工具包
  • VOCtest_06-Nov-2007.tar: 测试集,4952张图片
  • VOCtrainval_06-Nov-2007.tar: 训练和验证集,5011张图片
    \quad
    其中test和trainval的数据集目录结构一样,同时解压三个压缩包,最终会自动解压到一个文件夹下VOCdeckit。trainval和test数据集是从一个完整数据集划分来的,所以目录结构一样,且不存在冲突的图片命名。所以, 解压完成后相当于将两个子数据集合并成一个完整的大数据集 有train,val,trainval,test。
    \quad
    数据集文件结构介绍:
    \quad
    VOCtrainval_06-Nov-2007文件夹下
    VOCdevkit
    └─VOC2007
    ├─Annotations
    ├─ImageSets
    │ ├─Layout
    │ ├─Main
    │ └─Segmentation
    ├─JPEGImages
    ├─SegmentationClass
    └─SegmentationObject
    \quad

数据集文件夹分布情况如下:在这里插入图片描述
VOC 2007数据集结构的详细介绍: VOC 2007数据集结构

  • Annotation
    Annotations文件夹中存放的是xml格式的标签文件,每一个xml文件都对应于JPEGImages文件夹中的一张图片。
  • ImageSets
    ImageSets存放的是每一种类型的challenge对应的图像数据。
    \quad

核心知识点:
\quad

我们进行model训练,读取图像的时候,其实就是先从这个ImageSets文件夹中,找到对应任务的子文件夹,然后读取其中txt文本文档的图像ID号码, 接着按照这个ID号码去JPEGImages文件夹下寻找对应的图像。
\quad
ImageSets下的四个文件夹,如下:
在这里插入图片描述
当我们在faster-rcnn中运行训练和测试程序时,会在完整的大数据集中自动调用相对应的数据集。
(1) Action下存放的是人的动作(running、jumping等等,这也是VOC challenge的一部分)
在这里插入图片描述
(2) Layout下存放的是人体部位(head、hand、feet等等,这也是VOC challenge的一部分)
在这里插入图片描述
(3) Main下存放的是图像物体识别的数据,总共分为20类。
在这里插入图片描述
备注:

  • train.txt 是用来训练的图片文件的文件名列表 (训练集)
  • val.txt是用来验证的图片文件的文件名列表 (验证集)
  • trianval.txt用来训练和验证的图片文件的文件名列表 修改自己的图片检测模型时,仅需要修改该文件,即:将新的训练图像name list 去掉后缀,更新入trianval.txt文件。
  • test.txt 是用来测试的图片文件的文件名列表 (测试集)
    \quad
    train是网络模型在训练的时候用的,而val是网络模型在训练过程中测试用的。val是不影响训练的。在训练的时候可以得到train和val这两个数据集的误差率,利用这个误差率可以绘制出学习曲线,通过观察学习曲线,可以发现一些网络模型的问题,然后再根据这些问题去调整网络参数。test就是网络模型训练完毕测试用的。
    \quad
    Main文件夹下还包含了20个分类的***_train.txt、***_val.txt和***_trainval.txt。这些txt中的内容都差不多如下:
    在这里插入图片描述

前面的表示图像的name,后面的1代表正样本(即:表示当前图像中有该类物体),-1代表负样本(即:表示当前图像中,没有该类物体),偶尔也会出现0(即:0 表示当前图像中,该类物体只露出了一部分)。
_train中存放的是训练使用的数据,每一个class的train数据都有5717个;
_val中存放的是验证结果使用的数据,每一个class的val数据都有5832个;
_trainval将上面两个进行了合并,每一个class有11540个;
需要保证的是train和val两者没有交集,也就是训练数据和验证数据不能有重复,在选取训练数据的时候,也应该是随机产生的。

\quad
(4) Segmentation下存放的是可用于分割的图片的编号。
在这里插入图片描述

*_train中存放的是训练集的图片编号。
*_val中存放的是验证集的图片编号。
*_trainval是上面两者的合并集合。
train和val包含的图片没有交集。

  • JPEGImages
    JPEGImages文件夹中包含了PASCAL VOC所提供的所有的图片,包含训练图片和测试图片,共有17125张。图片均以“年份_编号.jpg”格式命名。图片的尺寸大小不一,所以在后面训练的时候需要对图片进行resize操作。
    图片的像素尺寸大小不一,但是横向图的尺寸大约在500ㄨ375左右,纵向图的尺寸大约在375ㄨ500左右,基本不会偏差超过100。(在之后的训练中,第一步就是将这些图片都resize到300ㄨ300或是500ㄨ500,所有原始图片不能离这个标准过远。)
  • SegmentationClass
    这里面包含了2913张图片,每一张图片都对应JPEGImages里面的相应编号的图片。
    图片的像素颜色共有20种,对应20类物体。
    在这里插入图片描述
  • SegmentationObject
    这里面同样包含了2913张图片,图片编号都与Class里面的图片编号相同。
    这里面的图片和Class里面图片的区别在于,这是针对Object的。
    在Class里面,一张图片里如果有多架飞机,那么会全部标注为红色。
    而在Object里面,同一张图片里面的飞机会被不同颜色标注出来。
    在这里插入图片描述
    \quad
    参考链接:
    关于VOC2007数据集的更多详细介绍,详见
    数据集:Pascal voc2007数据集分析
    VOC数据集介绍-VOCtrainval_06-Nov-2007文件结构和下载
    VOC数据集解析 VOC2007解析

5.下载预训练模型

首先,在/data/下创建子文件夹/data/pretrained_model;然后,下载预训练模型到/data/pretrained_model下,如VGG16,ResNet101等

VGG16: Dropbox, VT Server
ResNet101: Dropbox, VT Server

备注: Dropbox, VT Server是两个云存储公司开放的下载数据源,建议使用Dropbox的数据源进行下载。下载结束后,将这两个模型都放进/data/pretrained_model/文件夹中。

6.编译

  • 使用pip安装所有python依赖包
cd 进入data文件夹
pip install -r requirements.txt

安装python依赖包遇到错误:
ERROR: Could not open requirements file: [Errno 2] No such file or directory: 'requirements.txt',说明找不到’requirements.txt’文件,查找发现在data/的上一级,即:/work/elta/detectron/faster-rcnn.pytorch-pytorch-1.0文件夹下。在此处再执行pip install -r requirements.txt即可。

error: [Errno 13] Permission denied: '/usr/local/lib/处理方法 ,处理方法:在命令前面加sudo命令

备注:
在ubuntu系统下使用pip 命令安装包时,出现以下类似错误提示:
error: [Errno 13] Permission denied: '/usr/local/lib/python2.7/dist-packages/
那么,要用root权限,可以用sudo表示用root权限执行,所以,在命令前面加sudo。

  • 编译CUDA依赖环境

这里为pytroch1.0分支下的编译设置,编辑所需的cuda环境后,回到主目录。

cd lib
python setup.py build develop   # 不要使用sh make.sh

编译时遇到过两个报错

  • error: invalid command 'develop';
  • ImportError: cannot import name '_mask'
  • can’t import ‘imread’
  • Tips:要注意如果出现can’t import ‘imread’,请检查scipy的版本是否超过了1.0,因为1.0以上的版本里,scipy不再使用imread。
from imageio import imread   # 修改解决ImportError: cannot import name 'imread' from 'scipy.misc'

之前尝试通过pytorch0.4.0分支ReadMe配置好pytorch环境后,运行训练时出现错误ImportError: torch.utils.ffi is deprecated. Please use cpp extensions instead.,解决方法参考链接【已解决】ImportError: torch.utils.ffi is deprecated. Please use cpp extensions instead.
但限于版本更新和pytorch放弃对之前版本部分语法的支持,此问题是短时间内难以解决的死胡同,遂建议大家直接放弃0.4.0版本转入1.0.0版本。

7.训练

在训练之前需要根据自己的环境将trainval_net.pytest_net.py中的两个参数save_dirload_dir进行更改。

(1)如果使用VGG16在pascal_voc上训练faster R-CNN使用如下命令(具体参数根据自己的需要修改):

CUDA_VISIBLE_DEVICES=$GPU_ID python trainval_net.py \
                   --dataset pascal_voc --net vgg16 \
                   --bs $BATCH_SIZE --nw $WORKER_NUMBER \
                   --lr $LEARNING_RATE --lr_decay_step $DECAY_STEP \
                   --cuda

(2) 训练命令行示例——res101:

CUDA_VISIBLE_DEVICES=0 python trainval_net.py --dataset pascal_voc --net res101 --bs 4 --nw 0 --lr 0.001 --lr_decay_step 5 --cuda

或者

CUDA_VISIBLE_DEVICES=0,1 python trainval_net.py --dataset pascal_voc --net res101 --cuda 

参数说明:
\quad

  • CUDA_VISIBLE_DEVICES:指gpu的id,这得看你实验室服务器哪块gpu是闲置的。
  • –dataset:指训练数据集名称,此处以pascal-voc为例。
  • –net:你要使用的预训练模型,可以换为resnet101。
  • –bs:指的batch size。
    –epoch:指要训练的轮数。
  • –nw:指的是worker number,取决于你的Gpu能力,我用的是Titan Xp
    12G,所以选择4。稍微差一些的gpu可以选小一点的值。
  • –lr:指学习率
  • –cuda:指的是使用gpu。
    \quad
    BATCH_SIZE 和 WORKER_NUMBER 可以根据你的GPU情况来设置。
    \quad
    训好的model会存到models文件夹底下,此处暂时使用默认的训练参数。

8.测试

如果想评估VGG16预训练模型在pascal_voc测试集上的表现,使用如下命令:

python test_net.py --dataset pascal_voc --net vgg16 \
                   --checksession $SESSION --checkepoch $EPOCH --checkpoint $CHECKPOINT \
                   --cuda

要指定具体的checksessioncheckepochcheckpoint数值。如果你不知该如何设置,可以根据你训练出来的模型名字来设置。
在这里插入图片描述
设置示例:

# 批量测试
python test_net.py --dataset pascal_voc --net vgg16 \
                   --checksession 1 --checkepoch 1 --checkpoint 10021 \
                   --cuda

注意,这里的三个check参数,是定义了训好的检测模型名称,我训好的名称为faster_rcnn_1_20_10021,代表了checksession = 1,checkepoch = 20, checkpoint = 10021,这样才可以读到模型“faster_rcnn_1_20_10021”。训练中,源码代码默认设置的epoch为20,所以checkepoch选择20,也就是选择最后那轮训好的模型,理论上应该是效果最好的。下图就是我20次epochs的模型。
在这里插入图片描述

9.运行demo.py

如果你想要运行预训练模型去检测新的test图片,要先下载预训练模型或者训练你自己模型,然后把图片放到工作目录下(示例路径:/usr/detectron/faster-rcnn.pytorch-pytorch-1.0/images/)的images文件夹里,再运行如下命令:

python demo.py --net vgg16 \
               --checksession $SESSION --checkepoch $EPOCH --checkpoint $CHECKPOINT \
               --cuda --load_dir + 模型存放文件夹

除了指定那三个数值外,还要写清楚存放vgg16/pascal_voc/模型.pth的文件夹。例如:
在这里插入图片描述
demo命令行示例:

python demo.py --net res101  --checksession 1  --checkepoch 20 --checkpoint 10021 --cuda --load_dir models

此处我们需输入使用的网络(如:res101),以及训练好的模型路径(models)。我们测试的图片都在images文件夹里
\quad
作者提供了4张image做测试,默认测试完的图像会输出到images文件夹里,所以做完一次测试,images文件夹会有8张图片(输出图片命名规则是在原图像文件名后面加上"_det"),而原作者没有把他自己测试后的图片删去,所以大家在做demo测试时,别忘把以"_det"结尾的检测输出文件先删去,否则,测试完你的images文件夹可能会得到16张图像。 后续在参数修改部分,会详细介绍如何修改打框后图像的存放路径、包括保存生成的XML文件用于后续修改标注等:
当然,你可以放一些你自己在网上搜的图片在images文件夹里进行demo测试,看看效果。但检测类别一定在训练的类别中,否则,目标检测的结果就是随机标注了,意义不大~

faster-rcnn pytorch训练自定义Images文件和对应XML文件的model

我们仍然采用VOC2007数据集的结构分布框架,只是把我们自己的数据集“塞进去”,做适当调整即可。

1、VOC数据集制作:

将自己准备的images文件和对应的目标检测XML文件,做成VOC2007格式标准数据集,用于Faster-RCNN模型训练。

VOC2007格式要求: 图片名是六位数字,对应XML文件名也是六位数字。 数据集准备好之后,用数据集相应的替换掉VOC2007中的数据。具体位置如下:

一、JPEGImages文件夹
  将自己的数据集中所有的图片存放的这一文件夹下,图片数据的格式需要统一。
二、Annotations文件夹
  将自己数据集所有图片一一对应的xml格式的标签文件放于这一文件夹下。
三、ImageSets文件夹
  完成ImageSets\Main中trainval.txt文件的修改
  trainval.txt是训练和验证集,内容为文件名(去除".jpg"后缀),该文件中的图像list将全部用于目标检测的model训练,即:默认不划分train和val的比例 一般默认操作就OK了。
\quad
备注:
  如果想实现划分输入图像的train、val、test比例,需要同时修改ImageSets\Main文件夹下4个文件(test.txt、train.txt、trainval.txt、val.txt)。
  一般而言:在原始VOC2007数据集中,trainval大约占整个数据集的50%,test大约为整个数据集的50%;train大约是trainval的50%,val大约为trainval的50%。所以我们可参考以下代码来生成这4个txt文件。参考链接:faster-rcnn.pytorch-1.0指南(三)——制作PASCAL VOC2007数据集

生成这4个txt文件的示例代码:

import os
import random
 
trainval_percent = 0.5
train_percent = 0.5
xmlfilepath = '/home/VOC2007/Annotations'
txtsavepath = '/home/VOC2007/ImageSets/Main'
total_xml = os.listdir(xmlfilepath)
 
num=len(total_xml)
list=range(num)
tv=int(num*trainval_percent)
tr=int(tv*train_percent)
trainval= random.sample(list,tv)
train=random.sample(trainval,tr)
 
ftrainval = open(txtsavepath+'/trainval.txt', 'w')
ftest = open(txtsavepath+'/test.txt', 'w')
ftrain = open(txtsavepath+'/train.txt', 'w')
fval = open(txtsavepath+'/val.txt', 'w')
 
for i  in list:
    name=total_xml[i][:-4]+'\n'
    if i in trainval:
        ftrainval.write(name)
        if i in train:
            ftrain.write(name)
        else:
            fval.write(name)
    else:
        ftest.write(name)
 
ftrainval.close()
ftrain.close()
fval.close()
ftest .close()


2、修改/lib/datasets/pascal_voc.py里的检测类别:

VOC2007数据集的类别在路径"/faster-rcnn.pytorch/lib/datasets/pascal_voc.py"文件中已注明,示例如下:

原始标注类别为:

self._classes = ('__background__',  # always index 0
                         'aeroplane', 'bicycle', 'bird', 'boat',
                         'bottle', 'bus', 'car', 'cat', 'chair',
                         'cow', 'diningtable', 'dog', 'horse',
                         'motorbike', 'person', 'pottedplant',
                         'sheep', 'sofa', 'train', 'tvmonitor','plane')

这个文件里存着VOC数据库的classes,即:需要更改我们识别的类别,我的做法是把原classes注释掉,把自己的classes加进去。

此处修改如下:
在这里插入图片描述

可能发生如下错误:

  • assert(boxes[:,2]>=boxes[:,0]).all()
    基本上都会碰上,只要是你标注的框靠近边缘,都会出这个错误。表示:左上角坐标(x,y)可能为0,或标定区域溢出图片,而faster rcnn会对Xmin,Ymin,Xmax,Ymax进行减一操作,如果Xmin为0,减一后变为负值。但是,不用急,按照下面方法改,完美解决:https://blog.csdn.net/xzzppp/article/details/52036794
  • Keyerror:'width'
    该句指的是得到的图像数据库imdb文件没有‘width’,也就是没有读到图像的宽度值,而这个宽度值是通过图片读出来的,所以说明你的训练文件夹JPEGImage中没有ImagesSet\Main\trainval.txt里列出的图片,我查了下,图片都放进去了,那为啥还出错呢?
    原因在训练原数据集VOC时,图像数量是10021张(进行了数据增强),这时会保存训练信息至缓存中,文件路径为:/home/zhangxin/faster-rcnn.pytorch/data/cache/voc_2007_trainval_gt_roidb.pkl
    因此,=你在重新训练新数据集的时候,会读取这个缓存配置,以加快训练,那么,在更换训练数据集之后,就会报错了。我的新集合只有499张,所以训练时,由于读取缓存文件,故需要读的图像还是原来那10021张,那势必会找不到这10021张图像。
    解决方法把这个缓存文件voc_2007_trainval_gt_roidb.pkl删掉!!! 每次更新训练数据集都需要执行此操作

3、开始训练自己的数据集:

  1. 命令行运行trainval_net.py配置参数,开始model训练。示例如下:
CUDA_VISIBLE_DEVICES=0 python trainval_net.py --dataset pascal_voc --net res101 --bs 4 --nw 0 --lr 0.001 --lr_decay_step 5 --cuda
  1. 修改demo.py文件中的目标检测类别classes,具体同上:/lib/datasets/pascal_voc.py中classes的类别修改。
self._classes = ('__background__',  # always index 0
                         'id1', 'id2', 'id3', 'id4',
                         'id5', 'id6', 'id7', 'id8', 'id9',
                         'id10', 'id11', 'id12', 'id13',
                         'id14', 'id15', 'id18',
                         'id19', 'id26')
  1. 命令行运行demo.py配置参数,开始model测试。示例如下:
python demo.py --net res101 --checksession 1 --checkepoch 20 --checkpoint 233 --cuda --load_dir '/usr/detectron/faster-rcnn.pytorch-pytorch-1.0/tools/models/'

参考链接:
Faster RCNN(Pytorch) 配置过程记录及问题解决

使用faster-rcnn.pytorch训练自己数据集(完整版)

Faster-RCNN.Pytorch的使用

Pytorch版Faster R-CNN训练自己数据集

目标检测——Faster R-CNN 详解、Pytorch搭建、训练自己的数据集

faster-rcnn pytorch参数修改

基本参数:

  • base_lr:0.001
  • lr_policy:‘step’
  • step_size:30000
  • display:20
  • iteration: 数据进行一次前向-后向的训练
  • batchsize 每次迭代训练的图片数量
  • epoch 1个epoch就是将所有的训练图像全部通过网络训练一次

参数设置和计算:
\quad
(1)batchsize、epoch和iteration的关系计算:
例如:假如有1280000张图片,batchsize=256,则1个epoch需要1280000/256=5000次,若iteration 它的max-iteration=450000,则共有450000/5000=90个epoch;
(2)lr、stepsize和gamma的关系计算:
由于lr什么时候衰减与stepsize有关,减少多少与gamma有关,即:若stepsize=500, base_lr=0.01, gamma=0.1,则当迭代到第一个500次时,lr第一次衰减,衰减后的 l r = l r × g a m m a = 0.01 × 0.1 = 0.001 lr=lr×gamma=0.01×0.1=0.001 lr=lr×gamma=0.01×0.1=0.001,以后重复该过程,所以, stepsize是lr的衰减步长gamma是lr的衰减系数
(3)test_size, test_iter和test_interval的关系计算:
在训练过程中,每到一定的迭代次数都会测试,迭代次数是由test-interval决定的,如test_interval=1000,则训练集每迭代1000次测试一遍网络,而 test_size, test_iter, 和test图片的数量决定了怎样test, test-size决定了test时每次迭代输入图片的数量,test_iter就是test所有的图片的迭代次数,如:500张test图片,test_iter=100,则test_size=5, 而solver文档里只需要根据test图片总数量来设置test_iter,以及根据需要设置test_interval即可。
迭代次数修改max_iters=[80000, 40000, 80000, 40000]
分别对应rpn第1阶段,fast rcnn第1阶段,rpn第2阶段,fast rcnn第2阶段的迭代次数。

pytorch faster R-CNN源码测试、训练自己的数据集

修改数据读取路径:

数据读取路径可以直接赋值,在lib/datasets/pascal_voc.py中,把self._data_path修改为自己的数据路径,下面就是自己的数据classes类别。

train过程中修改训练模型保存路径:

trainval_net.py中修改模型保存的路径,对应参数'--save_dir',将default的值改为自己的model保存路径即可。

##############################################修改模型存放路径
  parser.add_argument('--save_dir', dest='save_dir',
                      help='directory to save models', default="/urs/detectron/faster-rcnn.pytorch-pytorch-1.0/tools/models/", type=str)

test过程中修改训练模型读入路径:

demo.py中修改读入模型的路径,对应参数'--load_dir',将default的值改为自己的model保存路径即可。

############################ 修改读入模型的路径
 parser.add_argument('--load_dir', dest='load_dir',
                      help='directory to load models',
                      default="/urs/detectron/faster-rcnn.pytorch-pytorch-1.0/tools/models/")

修改图像打标后test数据保存路径:

demo.py中修改保存图片的路径,把推断过后的图片另存一个文件夹中,
具体方法为:在parse_args中新增一个参数output_images,用于存放新生成的预测后画框的图片,同时修改图像保存代码,如下:

if vis and webcam_num == -1:
# cv2.imshow('test', im2show)
# cv2.waitKey(0)
result_path = os.path.join(args.output_images, imglist[num_images][:-4] + "_det.jpg") ###stt change output_images dir
cv2.imwrite(result_path, im2show)

添加保存图片xml文件的路径和生成对应xml文件:

demo.py中修改代码,用于生成并保存预测后的图片xml文件(减少后期标注量)具体修改参考如下:

pred_det = []
for j in xrange(1, len(pascal_classes)):
    inds = torch.nonzero(scores[:,j]>thresh).view(-1)
    # if there is det
    if inds.numel() > 0:        ### stt 判断预测出来的类别中是否有框
      cls_scores = scores[:,j][inds]   ### stt预测出来的所有得分
      _, order = torch.sort(cls_scores, 0, True)
      if args.class_agnostic:
        cls_boxes = pred_boxes[inds, :]
      else:
        cls_boxes = pred_boxes[inds][:, j * 4:(j + 1) * 4]  ###stt 预测出来的所有框
      
      cls_dets = torch.cat((cls_boxes, cls_scores.unsqueeze(1)), 1)  ### stt框和得分降成1维
      # cls_dets = torch.cat((cls_boxes, cls_scores), 1)
      cls_dets = cls_dets[order]
      # keep = nms(cls_dets, cfg.TEST.NMS, force_cpu=not cfg.USE_GPU_NMS)
      keep = nms(cls_boxes[order, :], cls_scores[order], cfg.TEST.NMS)   #### stt预测出来的框nms
      cls_dets = cls_dets[keep.view(-1).long()]
      ### stt add
      arr_2 =[]
      np.set_printoptions(suppress=True)  ###不以科学计数法保存
      arr_cls_det = cls_dets.cpu().numpy()   ###张量转数组
      arr_cls_det.astype(float)      ###列表数据转为float格式
      for i in arr_cls_det:
          arr_2.append(pascal_classes[j])  ###类别加入新的数组中
          arr_2 += map(int, i.tolist()[:4])   ###预测出来的框(四个坐标点)加入数组中
          pred_det.append(arr_2)     ###类比,框保存为一个列表,每张图片可能有多个预测框
      #print(arr_cls_det)
      #print((np.round(cls_dets)))
      if vis:
        im2show = vis_detections(im2show, pascal_classes[j], cls_dets.cpu().numpy(), 0.5)
#print(pred_det)
#######stt add save_txt and xml
save_txt = True
save_xml = True
### Write results:
for i in pred_det:
    if save_txt:  # Write to file
        img_name = im_file.split('/')[-1].split('.')[0]
        txt_path = os.path.join(args.output_images, 'txt_path')
        if not os.path.exists(txt_path):
            os.makedirs(txt_path)
        with open(txt_path + '/' + img_name + '.txt', 'a') as file:
            file.write(('%s, %g , %g, %g, %g ' + '\n') % (i[0], i[1], i[2], i[3], i[4]))
        txtfile = os.path.join(txt_path, img_name + '.txt')
    ###stt _add start write_xml
    if save_txt and save_xml:
        Anno_path = os.path.join(args.output_images, 'Annotations')
        if not os.path.exists(Anno_path):
            os.makedirs(Anno_path)
        outdir = os.path.join(Anno_path,
                              img_name + '.xml')
        txt2xml(pascal_classes, txtfile, im_file, outdir)
####stt add end
misc_toc = time.time()
nms_time = misc_toc - misc_tic

参考链接:
pytorch 版fasterrcnn 跑通代码增加保存xml的功能

猜你喜欢

转载自blog.csdn.net/weixin_42782150/article/details/109820615