Mask RCNN训练自己的数据集

这篇具有很好参考价值的文章主要介绍了Mask RCNN训练自己的数据集。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Mask RCNN作为实例分割的经典算法,对于图像分割的初学者来说,还是很有必要了解下的。

原mask rcnn的Tensorflow版本是1.13,这里提供tf2.5的mask rcnn的github源码地址:https://github.com/zouyuelin/MASK_RCNN_2.5.0

目录

一、制作数据集

1.下载安装labelme

 2.标注数据集

3.labelme数据集转化

二、模型训练

1.环境搭建

 2.模型配置

2.1 datasets.py修改

2.1.1 目录名称修改

2.2.2 添加类别

2.2.2 config配置

3 开始训练

4. 查看日志

 三.模型测试

一、制作数据集

1.下载安装labelme

利用labelme制作实例分割数据集_Jiazhou_garland的博客-CSDN博客_labelme实例分割利用labelme制作实例分割数据集一、软件安装与环境配置二、利用labelme做实例分割标记三、利用labelme生成voc与coco格式数据集关于coco数据集的理解其它一些可能出现的问题一、软件安装与环境配置参考上一篇博客二、利用labelme做实例分割标记容易出现的一些问题:当一张图片里同个类别有多个物体时,均使用同一种类名称作为标签进行标注(因为后文coco数据集格式会给同种物体单独分序号)。如下图三人均属于person类。当一张图片里某个颗粒被遮挡时,利用labelme标签https://blog.csdn.net/qq_43019433/article/details/124583352

 2.标注数据集

可以自己找图片,用labelme进行标注,标注工作很枯燥耗时,如果不想自己标注,可以使用本项目提供的标注好的数据集。 该数据集饮水机是自己标注的,其他几个类是从coco数据集转化成labelme标注格式的。从coco数据集提取自己想要的类和数量,转化成labelme格式是很实用的操作,不用自己手工标注,转换脚本refine_by_class.py配置如下:

mask rcnn训练,图像分割,人工智能,计算机视觉,python

import json
import os

import matplotlib.pyplot as plt
from PIL import Image
from pycocotools.coco import COCO
from tqdm import tqdm

# 需要设置的路径
savepath="D:/python/workspace/temp/"
datasets_list=['train2017','val2017']
limit = 3000 #每个类提取数量

#coco有80类,这里写要提取类的名字,以person为例
classes_names = ['person','dog','cat']
#包含所有类别的原coco数据集路径
'''
目录格式如下:
$COCO_PATH
----|annotations
----|train2017
----|val2017
----|test2017
'''
dataDir= 'E:/datasets/coco2017/'
 
# 检查目录是否存在,如果存在,先删除再创建,否则,直接创建
def mkr(path):
    if not os.path.exists(path):
        os.makedirs(path)  # 可以创建多级目录

def id2name(coco):
    classes=dict()
    for cls in coco.dataset['categories']:
        classes[cls['id']]=cls['name']
    return classes
 

def refine(coco,dataset,img,classes,cls_ids,show=True):
    img_dir = savepath+'/'+dataset+ '/images/'
    anno_dir = savepath+'/'+dataset + '/annotations/'
    mkr(img_dir)
    mkr(anno_dir)

    global dataDir
    I=Image.open('%s/%s/%s/%s'%(dataDir,dataset,dataset,img['file_name']))
    #通过id,得到注释的信息
    annIds = coco.getAnnIds(imgIds=img['id'], catIds=cls_ids, iscrowd=None)
    # print(annIds)
    anns = coco.loadAnns(annIds)
    # print("### ", anns)
    # coco.showAnns(anns)
    #构建labelme格式json数据
    labelme_json ={"version":"","flags":{},"shapes":[],"imagePath":"","imageData":"","imageHeight":"","imageWidth":""}
    labelme_json["imageHeight"] = img["height"]
    labelme_json["imageWidth"] = img["width"]
    labelme_json["imagePath"] = "..\\images\\"+img['file_name']
    objs = []

    for ann in anns:
        class_name=classes[ann['category_id']]
        if class_name in classes_names:
            #提取bbox
            if 'bbox' in ann:
                bbox=ann['bbox']
                xmin = int(bbox[0])
                ymin = int(bbox[1])
                xmax = int(bbox[2] + bbox[0])
                ymax = int(bbox[3] + bbox[1])
                obj = [class_name, xmin, ymin, xmax, ymax]
                objs.append(obj)
                # draw = ImageDraw.Draw(I)
                # draw.rectangle([xmin, ymin, xmax, ymax])
            #提取分割标注
            x = ann['segmentation'][0][::2]  # 奇数个是x的坐标
            y = ann['segmentation'][0][1::2]  # 偶数个是y的坐标
            shape = {"label": class_name, "points": [], "group_id": ann['category_id'], "shape_type": "polygon","flags": {}}
            for j in range(len(x)):
                shape['points'].append([x[j], y[j]])
            labelme_json['shapes'].append(shape)
            print("### labelme json: ",labelme_json)

            #保存json和图片
            with open(anno_dir+class_name+"_"+img['file_name'].replace(".jpg",".json"), 'w', encoding='utf-8') as json_file:
                json.dump(labelme_json, json_file, ensure_ascii=False)
            I.save(img_dir+img['file_name'])
            print("write image and json file success!")
            if show:
                plt.figure()
                plt.axis('off')
                plt.imshow(I)
                plt.show()
    return objs
 
for dataset in datasets_list:
    #./COCO/annotations/instances_train2017.json
    annFile='{}/annotations_trainval2017/annotations/instances_{}.json'.format(dataDir,dataset)
 
    #使用COCO API用来初始化注释数据
    coco = COCO(annFile)
 
    #获取COCO数据集中的所有类别
    classes = id2name(coco)
    print(classes)
    #[1, 2, 3, 4, 6, 8]
    classes_ids = coco.getCatIds(catNms=classes_names)
    print(classes_ids)
    count = {}
    for cls in classes_names:
        count[cls] = 0
        #获取该类的id
        cls_id=coco.getCatIds(catNms=[cls])
        img_ids=coco.getImgIds(catIds=cls_id)
        print(cls,len(img_ids))
        # imgIds=img_ids[0:10]
        for imgId in tqdm(img_ids):
            if(count[cls] > limit):
                print("### class_id:{}数量已满足{}".format(cls,limit))
                break
            img = coco.loadImgs(imgId)[0]
            filename = img['file_name']
            # print(filename)
            try:
                # 第五个参数,cls_id表示只提取图片里的这一个类,classes_ids表示提取图片符合要求的多个类
                objs=refine(coco, dataset, img, classes,cls_id,show=False)
                count[cls] += 1
            except Exception as e:
                print(e)
                continue
            print(objs)
            # save_annotations_and_imgs(coco, dataset, filename, objs)
            

 转换成功后会生成annotation和images两个文件夹,一个是labelme标注的json,一个是原始图片。网盘下载链接:https://pan.baidu.com/s/13OPmawjn_aj_qH35H7yOtQ         提取码:6666

3.labelme数据集转化

 将训练集和验证集转换成项目需要的数据格式,使用如下的labelme_json_to_dataset.py代码

mask rcnn训练,图像分割,人工智能,计算机视觉,python

# -*- coding: utf-8 -*-
import argparse
import json
import os
import os.path as osp
import traceback
import warnings

import imgviz
import PIL.Image
import yaml

from labelme.logger import logger
from labelme import utils
import base64


def main():
    # warnings.warn("This script is aimed to demonstrate how to convert the\n"
    #               "JSON file to a single image dataset, and not to handle\n"
    #               "multiple JSON files to generate a real-use dataset.")
    parser = argparse.ArgumentParser()
    parser.add_argument('json_file')
    parser.add_argument('-o', '--out', default=None)
    args = parser.parse_args()

    json_file = args.json_file
    if args.out is None:
        out_dir = osp.basename(json_file).replace('.', '_')
        out_dir = osp.join(osp.dirname(json_file), out_dir)
    else:
        out_dir = args.out
    if not osp.exists(out_dir):
        os.mkdir(out_dir)
    filepath =  json_file.replace("/\\", "/")
    print("##### dir_path:",filepath)
    count = os.listdir(filepath)
    for i in range(0, len(count)):
        path = os.path.join(json_file, count[i])
        if os.path.isfile(path):
            try:
                data = json.load(open(path))

                if data['imageData']:
                    imageData = data['imageData']
                else:
                    imagePath = os.path.join(os.path.dirname(path), data['imagePath'])
                    with open(imagePath, 'rb') as f:
                        imageData = f.read()
                        imageData = base64.b64encode(imageData).decode('utf-8')
                img = utils.img_b64_to_arr(imageData)
                label_name_to_value = {'_background_': 0}
                for shape in data['shapes']:
                    label_name = shape['label']
                    if label_name in label_name_to_value:
                        label_value = label_name_to_value[label_name]
                    else:
                        label_value = len(label_name_to_value)
                        label_name_to_value[label_name] = label_value

                # label_values must be dense
                label_values, label_names = [], []
                for ln, lv in sorted(label_name_to_value.items(), key=lambda x: x[1]):
                    label_values.append(lv)
                    label_names.append(ln)
                assert label_values == list(range(len(label_values)))

                lbl = utils.shapes_to_label(img.shape, data['shapes'], label_name_to_value)

                captions = ['{}: {}'.format(lv, ln)
                            for ln, lv in label_name_to_value.items()]
                lbl_viz = imgviz.label2rgb(label=lbl, img=imgviz.rgb2gray(img), label_names=label_names, loc='rb')
                # lbl_viz = utils.draw_label(lbl, img, captions)

                out_dir = osp.basename(count[i]).replace('.', '_')
                save_folder_name = out_dir  # 文件夹名称
                split_file_name = osp.basename(count[i]).split('.')  # 分隔文件名和文件类型
                save_file_name = split_file_name[0]

                out_dir = osp.join(osp.dirname(count[i]), out_dir)

                if not osp.exists(json_file + '/' + 'labelme_json'):
                    os.mkdir(json_file + '/' + 'labelme_json')
                mask_info = json_file + 'labelme_json'
                out_dir1 = mask_info + '/' + save_folder_name
                if not osp.exists(out_dir1):
                    os.mkdir(out_dir1)

                PIL.Image.fromarray(img).save(osp.join(out_dir1, 'img.png'))  # save_file_name文件名
                # PIL.Image.fromarray(lbl).save(osp.join(out_dir1, save_file_name+'_label.png'))
                utils.lblsave(osp.join(out_dir1, 'cv2_mask.png'), lbl)
                PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir1, 'label_viz.png'))

                if not osp.exists(json_file + '/' + 'cv2_mask'):
                    os.mkdir(json_file + '/' + 'cv2_mask')
                mask_save2png_path = json_file + '/' + 'cv2_mask'

                if not osp.exists(json_file + '/' + 'pic'):
                    os.mkdir(json_file + '/' + 'pic')
                img_save2png_path = json_file + '/' + 'pic'

                utils.lblsave(osp.join(mask_save2png_path, save_file_name + '.png'), lbl)
                PIL.Image.fromarray(img).save(osp.join(img_save2png_path, save_file_name + '.png'))

                with open(osp.join(out_dir1, 'label_names.txt'), 'w') as f:
                    for lbl_name in label_names:
                        f.write(lbl_name + '\n')

                # warnings.warn('info.yaml is being replaced by label_names.txt')
                info = dict(label_names=label_names)
                with open(osp.join(out_dir1, 'info.yaml'), 'w') as f:
                    yaml.safe_dump(info, f, default_flow_style=False)

                print('Saved to: %s' % out_dir1)
            except Exception as e:
              traceback.format_exc()


if __name__ == '__main__':
    main()

转化成功后会生成三个文件,cv2_mask(图片掩码),labelme_json(标注信息)和pic(原图)

mask rcnn训练,图像分割,人工智能,计算机视觉,python

将训练集和验证集复制到项目的datasets目录

mask rcnn训练,图像分割,人工智能,计算机视觉,python

二、模型训练

1.环境搭建

用Anaconda创建一个虚拟环境,切换至虚拟环境,运行项目中的requirements.txt,会下载模型所需的库文件。注:将requirements.txt中的tensorflow改为tensorflow-gpu,版本推荐用2.5.0,比较新的高版本可能会有兼容问题。如果下载过程太慢,可能是没有切换镜像源,这里使用的清华镜像源:

pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple

mask rcnn训练,图像分割,人工智能,计算机视觉,python

 2.模型配置

2.1 datasets.py修改

2.1.1 目录名称修改

项目的目录名称和脚本生成的目录名不一样,这里改为和datasets里一致的目录名称。

mask rcnn训练,图像分割,人工智能,计算机视觉,python

2.2.2 添加类别

数据集只训练了5个类,依次添加进list,id和名称自己取的,第一个参数都是‘shapes’。mask rcnn训练,图像分割,人工智能,计算机视觉,python

2.2.2 config配置

config比较常见的参数,已经提取到datasets.py里配置,其他的用config.py默认配置。配置详解请看这篇文章:Mask-RCNN应用 - 结合源码详细解析Config.py_天木青的博客-CSDN博客

mask rcnn训练,图像分割,人工智能,计算机视觉,python

3 开始训练

train.py设置对应的train和val路径,运行脚本开始训练。当第一次训练时,系统需要一段时间给数据集生成.npz的中间文件,以后训练会直接读这些文件,加快训练。

mask rcnn训练,图像分割,人工智能,计算机视觉,python当控制台没有报错,且出现以下进度条时说明模型可以正常训练。训练非常慢的话,有可能是使用cpu训练的,没有调到GPU,检查cuda和cudnn是否安装正确,通过nvidia-smi可查看GPU使用情况。 

mask rcnn训练,图像分割,人工智能,计算机视觉,python

4. 查看日志

训练得到的权重模型文件在logs文件夹下
在tensorbord中查看训练过程的各指标变化趋势

tensorboard --logdir logs/

mask rcnn训练,图像分割,人工智能,计算机视觉,python

 mask rcnn训练,图像分割,人工智能,计算机视觉,python

 三.模型测试

测试用自己写的脚本,支持图片和视频测试,NUM_CASSESL和class_names需要根据实际修改

import os
import sys

import cv2
import skimage.io

from tensorflow.python.client import device_lib

from ecnu.draw_segmention_utils import draw_segmentation

print(device_lib.list_local_devices())
import tensorflow as tf
print("GPU状态:",tf.test.is_gpu_available())

ROOT_DIR = os.path.abspath("../")

sys.path.append(ROOT_DIR)

from mrcnn.config import Config
from datetime import datetime
import mrcnn.model as modellib
from mrcnn import visualize

sys.path.append(os.path.join(ROOT_DIR, "samples/coco/"))

MODEL_DIR = os.path.join(ROOT_DIR, "logs/")
# MODEL_DIR = os.path.join(ROOT_DIR, "logs/")

# COCO_MODEL_PATH = os.path.join(MODEL_DIR, "mask_rcnn_shapes_0004.h5")
COCO_MODEL_PATH = os.path.join(MODEL_DIR, "mask_rcnn_shapes_0368.h5")

IMAGE_DIR = os.path.join(ROOT_DIR, "testdata")


# IMAGE_DIR = os.path.join(ROOT_DIR, "images")

class ShapesConfig(Config):
    NAME = "shapes"

    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

    NUM_CLASSES = 1 + 5

    DETECTION_MIN_CONFIDENCE = 0.8  # 所有小于0.7的置信度都认为内部不包含物体
    TRAIN_ROIS_PER_IMAGE = 512
    RPN_TRAIN_ANCHORS_PER_IMAGE = 512
    # Length of square anchor side in pixels
    # RPN_ANCHOR_SCALES = (32, 64, 128, 256,512)


class InferenceConfig(ShapesConfig):
    GPU_COUNT = 1
    IMAGES_PER_GPU = 1

class_names = ['BG','bottle','chair','laptop','mouse','keyboard','person']


if __name__ == "__main__":
    i = 1
    # video_path = ''
    video_path= 'video/test.mp4'

    config = InferenceConfig()
    model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
    model.load_weights(COCO_MODEL_PATH, by_name=True)
    i = i + 1
    file_names = next(os.walk(IMAGE_DIR))[2]
    #    image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names)))
    image = skimage.io.imread(os.path.join(IMAGE_DIR, "000004.jpg"))
    a = datetime.now()

    results = model.detect([image], verbose=5)
    b = datetime.now()

    print("time:", (b - a).seconds)
    r = results[0]
    visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])

    if video_path:
        # 1、获取视频的读取
        vcapture = cv2.VideoCapture(video_path)
        width = int(vcapture.get(cv2.CAP_PROP_FRAME_WIDTH))
        height = int(vcapture.get(cv2.CAP_PROP_FRAME_HEIGHT))
        fps = vcapture.get(cv2.CAP_PROP_FPS)

        # 2、定义video writer后续写入
        file_name = "./segmentation_{}".format(video_path.split("/")[-1])
        vwriter = cv2.VideoWriter(file_name,
                                  cv2.VideoWriter_fourcc(*'mp4v'),
                                  fps, (width, height))

        # 3、循环获取每帧数据进行处理,完成之后写入本地文件
        count = 0
        success = True
        while success:
            print("帧数: ", count)
            # 读取图片
            success, image = vcapture.read()
            if success:
                # OpenCV 返回的BGR格式转换成RGB
                image = image[..., ::-1]
                # 模型检测mask
                r = model.detect([image], verbose=0)[0]
                # 画出区域
                # 画出区域
                segmentation = visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'], class_names, r['scores'])
                # RGB -> BGR
                segmentation = segmentation[..., ::-1]
                # 添加这张图到video writer
                vwriter.write(segmentation)
                count += 1
        vwriter.release()

测试效果图,作为当时sota的经典算法效果还行,想要更好的分割效果,下篇文章会介绍目前性能sota的yolov8分割算法。

mask rcnn训练,图像分割,人工智能,计算机视觉,pythonmask rcnn训练,图像分割,人工智能,计算机视觉,python

mask rcnn训练,图像分割,人工智能,计算机视觉,python 

 文章来源地址https://www.toymoban.com/news/detail-611933.html

 

到了这里,关于Mask RCNN训练自己的数据集的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Mask RCNN详解

            Mask R-CNN是对Faster R-CNN的直观扩展,网络的主干有RPN转换为主干网络为ResNet的 特征金字塔网络(FPN),同时 添加了一个分支用于预测每个感兴趣区域(RoI)上的分割掩模,与现有的用于分类和边界盒回归的分支并行(图1)。 掩模分支是一个应用于每个RoI的小FCN,以像素

    2023年04月11日
    浏览(24)
  • MASK-RCNN tensorflow环境搭建

    此教程默认你已经安装了Anaconda,且tensorflow 为cpu版本。为什么不用gpu版本,原因下面解释。 因为tensorflow2.1后的gpu版·,不支持windows。并且·只有高版本的tensorflow才对应我的CUDA12.2; 而且,我之前安装了pytorch跑tolov8,cuda都很高。安装tensorflow-gpu的话,需要重新安装我的cuda,

    2024年02月06日
    浏览(85)
  • Mask RCNN 超详细图文入门(含代码+原文)

    代码地址:maskrcnn-benchmark(PyTorch) 我在入门学习计算机视觉的适合,看一些经典的论文原文比较吃力。于是通过看各种参考文献及查阅各路资料,入门的角度写了一些博客,希望能够和大家一起进步。 笔者在阅读《Mask R-CNN》原文后,根据自身理解及查阅资料,以入门角度尽可

    2024年02月07日
    浏览(45)
  • Mask RCNN网络结构以及整体流程的详细解读

    Mask RCNN是在Faster RCNN的基础上增加了mask head用于实例分割的模型。 总体来说,Mask RCNN网络结构可以分为: BackBone(ResNet+FPN) — RPN网络(Region Proposal Network) — ROI Head(ROIAlign + cls head + bbox head + mask head) 整体网络结构如下(来自原论文https://arxiv.org/pdf/1703.06870.pdf): Backbone主要由R

    2024年02月13日
    浏览(27)
  • mmdetection 中 Mask Rcnn检测结果可视化(DICE计算、PR曲线绘制等)

    mmdetection中的Mask Rcnn是一个很不错的检测网络,既可以实现目标检测,也可以实现语义分割。官方也有很详细的doc指导,但是对新手来说并不友好,刚好之前笔者写的mmlab系列里面关于可视化都还没有一个详细的文档,也在此一并介绍。 具体怎么制作自己的数据集和训练自己

    2024年02月12日
    浏览(36)
  • Faster RCNN训练自己的数据集【傻瓜式教程】

    本文采用的源码是:https://github.com/dBeker/Faster-RCNN-TensorFlow-Python3 由于本文是小白教程,光写几个环境怕有人配置不好或者配置版本搞乱。Faster RCNN配置环境比较复杂。我在这直接贴图我的环境版本图: 先安装tensorflow-gpu,然后依次安装cython、opencv-python、easydict、Pillow、matplot

    2024年02月02日
    浏览(28)
  • Mask2Former来了!用于通用图像分割的 Masked-attention Mask Transformer

    原理https://blog.csdn.net/bikahuli/article/details/121991697 源码解析 论文地址:http://arxiv.org/abs/2112.01527 项目地址:https://bowenc0221.github.io/mask2former Mask2Former的整体架构由三个组件组成: 主干特征提取器:主干特征提取器从输入图像中提取低分辨率特征。在Mask2Former中,主干特征提取器通

    2024年02月02日
    浏览(35)
  • 【mmdetection】用自己的coco数据集训练mask r-cnn并进行验证、测试,推理可视化,更改backbone,只针对某一标签进行训练

    本人呕心沥血从无到有的摸索,自己边尝试边整理的,其实耐心多看官方文档确实能找到很多东西(下面有官方文档的链接这里就不重复粘贴了),也为了方便我自己copy语句嘻嘻~ 为什么不是用Windows,作为一个小白我一开始真的想用windows,因为我懒得配双系统,但是没办法

    2024年02月04日
    浏览(36)
  • OpenCV中使用Mask R-CNN实现图像分割的原理与技术实现方案

    本文详细介绍了在OpenCV中利用Mask R-CNN实现图像分割的原理和技术实现方案。Mask R-CNN是一种先进的深度学习模型,通过结合区域提议网络(Region Proposal Network)和全卷积网络(Fully Convolutional Network),实现了对图像中物体的精确分割。本文首先阐述了Mask R-CNN的原理,然后详细

    2024年02月03日
    浏览(33)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包