Matterport版Mask RCNN——训练自己的数据集——踩坑小记

Matterport版Mask RCNN——训练自己的数据集——踩坑小记

  • 前言
  • 一、基本配置
    • 系统配置
    • Matterport环境配置
      • Conda 虚拟环境
      • Pycharm的安装和使用上述环境
  • 二、制作自己的数据集
    • 实现默认程序测试结果
    • 制作labelme数据集
        • 安装labelme
        • 改进的json_to_dataset.py
      • 准备好的数据目录结构
  • 三、自定义数据集训练
      • 增加头文件include
      • 确认yaml读取函数
      • 代码修改内容总结

前言

最近基于一台新机器,配置了深度学习工作站,并跑起了matterport版的Detectron。中间各种坑,现在记录如下,有后来者看到诸坑,按照我说的方案解决即可。

一、基本配置

系统配置

操作系统:Ubuntu 16.04
CUDA:Version 9.0.176
CUDNN:7.0.5
Anaconda: 3.6

查看自己电脑的CUDA和CUDNN版本的命令:

cuda 版本
cat /usr/local/cuda/version.txt
cudnn 版本
cat /usr/local/cuda/include/cudnn.h | grep CUDNN_MAJOR -A 2

Matterport环境配置

Conda 虚拟环境

这里主要指的是:基于Anaconda为Mask RCNN创造一个conda的虚拟环境。
方法大体可参照:

https://blog.csdn.net/wc781708249/article/details/79438972
使用Keras和Tensorflow设置和安装Mask RCNN

注意:一定要为Mask RCNN单独创造一个虚拟环境,因为后续调试要用到Pycharm,Pycharm直接加载这个环境就可以运行程序了。

Pycharm的安装和使用上述环境

为何要使用Pycharm,因为相比于matterport提供的ipynb格式的代码,这个更方便调试。

安装大体可以参考:
https://blog.csdn.net/anjingshen/article/details/80038316
Pycharm 2018.1.1 使用anaconda 3中已创建的环境

略有不同的是,最后一步,
按照里面的步骤从pycharm链接虚拟环境中的python3.exe。
(因为我用的是anaconda3.6,对应python3)

请注意上文以及下文的“大体可参考”中的“大体”表示:
我当初不是依靠着这篇博文解决的问题,但是我暂时没从历史记录里找到当时的网页,因此我临时给大家找了另一篇但是和我方法相同的博文(如果有时间我会再寻找)

二、制作自己的数据集

这一块,网上诸多大神都搞出来了自己的版本,我也是博览群雄,然后实现出来了。因此,下面,我不打算做重复的黏贴工作,我会把我用到的链接贴过来(也是尊者每个作者的辛劳),然后把我遇到的问题写出来,你可以避免这个坑。

实现默认程序测试结果

首先,ipynb转py这个用jupyter来另存为转化的流程也不多说了,网上都有教程。

也就是你会获得:
/Mask_RCNN/samples/demo.py
/Mask_RCNN/samples/shapes/train_shape.py
两个函数,首先要跑通这两个函数,表示matterport程序安装、运行成功。

额外说一句,稳妥起见,你可以刚装好matterport之后,直接在官方默认的jupyter notebook下测试上述两个文件,即demo.ipynb和train_shape.ipynb,如果有问题能早发现。毕竟,更好的调试环境和程序能否跑通这两个是并行而不是串行的工作。

下面是网上随便找的一张图的测试结果,以及matterport训练自己数据集(三角、圆、方块)的跑通结果图。

Matterport版Mask RCNN——训练自己的数据集——踩坑小记_第1张图片

Matterport版Mask RCNN——训练自己的数据集——踩坑小记_第2张图片
两只兔子表示被无视了。
Matterport版Mask RCNN——训练自己的数据集——踩坑小记_第3张图片

制作labelme数据集

安装labelme

这个部分不多说了吧,网上教程一大把,
大体应该有这两个步骤吧,不详细说了。
pip install pyqt5
pip install labelme

安装完了,在命令行端,输入labelme可以打开该软件。

改进的json_to_dataset.py

为何要改进,目的有二:
我们需要批处理而不是一个一个json文件来转化。
默认labelme程序生成的是16位mask,我们需要8位,还要转化。

这个网上版本很多,但是很多都有错误或者功能不全。
我现在选了一个最优的版本也是我用的版本,然后说怎么改。
https://blog.csdn.net/u014513323/article/details/81166997
改进json_to_dataset.py,使得能够批量处理多张图片并一步建好所需目录及相关mask文件,运行后,在json文件夹中会出现mask_png、labelme_json文件夹,mask_png中存放的是所有8位掩码文件!

按照文中所述,操作步骤有两步:

  1. 将本程序替换掉labelme/cli中的相应文件—json_to_dataset.py
    编者注:在前面的matterport安装中,你安装了labelme,这个labelme/cli是说的anaconda中的labelme,在你自己的ubuntu系统中,这个文件所在位置应该是类似如下地址:
    /home/你的名字/anaconda3/envs/MaskRCNN/lib/python3.6/site-packages/labelme/cli
  2. 在cmd中输入python json_to_dateset.py /path/你的json文件夹的路径
    编者注:我是不用加python,你也可以不加,直接这样搞:
    labelme_json_to_dataset /home/你的名字/Downloads/jsonfiles
    Downloads/jsonfiles是你存放json文件的位置,这个位置随意。

然后,是原文中有两个错误需要修改:
文中有几行包含“mkdir”和“\”符号,比如第53行:

os.mkdir(json_file + '\\' + 'labelme_json')

错误一:mkdir无法生成多级目录,需要makedirs。
错误二:“\”似乎有问题,生成了一堆文件名中含有“\”的文件,我改成了“/”
所以,包含包含“mkdir”和“\”符号的这几行都要改,类似这样:

os.makedirs(json_file + '/' + 'labelme_json')

然后就运行成功了。

准备好的数据目录结构

自定义数据集训练和检测,基本上是参考着一篇高访问量的牛文来实现的,因此数据格式也是参考他的。
先直接列出来数据结构和文件命名,牛文自己以及其他博文语焉不详,我这里给你写清楚。
注意,以下命名并非强制,而是与牛文代码相一致,看着不爽,调通后自己改名字也可以。但是调通之前,请严格按照下图设置。
Matterport版Mask RCNN——训练自己的数据集——踩坑小记_第4张图片
多少年不画图,画个图耗掉半条命。

  1. mask表示8位掩膜,里面文件命名如1.png,2.png。
  2. rgb表示原图,就是你自己的数据集原图,但是这是labelme生成出来的,文件命名如rgb_1.png,rgb_2.png。
  3. total是yaml等文件的根目录文件夹名,没有什么道理叫这个名字,不爽可以后续删改。但是暂时可以照搬。而且我打赌你调通以后也就懒得再改了。total下面有形如rgb_x_json等文件夹,每个里面有info.yaml和label_names.txt。
  4. 上述labelme_json_to_dataset命令生成的文件名未必与图示要求的一样,暂时来说,你可以先标记几个样本,手动修改名称,按照上述图示放置到正确的目录中,先把程序跑通再说。程序没问题了,你也制作了很多样本的json文件后,必然面对着大批量的json文件转化工作,一个个修改命名不现实,届时可以再度完善json_to_dataset.py文件,使它生成的数据直接就是图示的名称。

三、自定义数据集训练

牛文:
https://blog.csdn.net/l297969586/article/details/79140840
Mask RCNN训练自己的数据集

以下用牛文代指该文。

请首先参照此文添加新的DrugDataset类、修改代码。别怕麻烦。

然后再添加或者注意以下三点:

增加头文件include

from PIL import Image
import yaml
import skimage.io

确认yaml读取函数

当初忘了是哪里拷贝过来的,一开始from_yaml_get_class函数有问题,就是序号和名称位置反了。又找了个正确版本改好了。总之,一定确认yaml函数如下,我拷贝过来的版本似乎漏了这句话labels = list(labels.keys())。

    def from_yaml_get_class(self, image_id):
        info = self.image_info[image_id]
        with open(info['yaml_path']) as f:
            temp = yaml.load(f.read())
            labels = temp['label_names']
            labels = list(labels.keys())
            del labels[0]
        return labels

这个版本是对的。也是现在牛文中的版本。

代码修改内容总结

最后的修改后的train_shape.py的代码内容应该是:

  1. 新的更全的头文件
  2. 根据你自己的需求,轻微调参修改的class ShapesConfig(Config)类
  3. 被注释掉的class ShapesDataset(utils.Dataset)及其诸函数。
  4. 新添加的class DrugDataset(utils.Dataset)类及其函数。
  5. 代码主体修改添加了dataset_root_path,img_floder,mask_floder,yaml_floder的位置和修改图像大小那一段。(注:应为folder,原作者笔误。)
  6. 添加train与val数据集准备 dataset_train = DrugDataset()和 dataset_val = DrugDataset()那几段。
  7. 后续# Which weights to start with?那一段不动。
  8. 注释掉model.train(dataset_train,dataset_val,learning_rate=config.LEARNING_RATE/10,epochs=50,layers=“all”)之后的代码就好了。

至此,训练部分就应该可以进行了。测试部分比着葫芦画瓢改改也就行了。之前的train_shape代码最后本身就有测试代码,按照自己的数据稍作改动即可。

大家先看着,有问题我再修改补充。(待续)

你可能感兴趣的:(Matterport版Mask RCNN——训练自己的数据集——踩坑小记)