赞
踩
在使用Mask R-CNN训练自己的数据时,需要提前了解Mask R-CNN的标注工具以及跑通Mask R-CNN的Demo。下面的两篇博客分别介绍了Mask R-CNN标注工具以及如何跑通Mask R-CNN的Demo。
使用Keras与Tensorflow安装Mask RCNN并跑通Demo
在了解了Mask RCNN标注工具以及跑通了Demo后,我们要根据实际的问题来进行训练自己的Mask RCNN模型。由于数据集不方便公开,下面简单介绍训练的整个流程。
1 准备数据集
训练Mask RCNN模型只需要4个文件夹的数据,分别是原图,json文件,生成的json文件夹以及label.png。
注意:在使用labelme标注后生成的json文件夹中的label.png图片是16位的,但是Opencv读取16位的时候会出现错误,因此我们需要通过脚本将16位的label.png转为8位的,脚本大家可以在这里下载。labelme16位转8位下载
文件夹数据:
4个文件夹中的内容分别是
cv2_mask json
labelme_json pic
2 训练模型
准备好数据集后,我们就需要去训练我的模型。
训练数据的源代码:
- # -*- coding: utf-8 -*-
-
- import os
- import sys
- import random
- import math
- import re
- import time
- import numpy as np
- import cv2
- import matplotlib
- import matplotlib.pyplot as plt
- import tensorflow as tf
- from mrcnn.config import Config
- #import utils
- from mrcnn import model as modellib,utils
- from mrcnn import visualize
- import yaml
- from mrcnn.model import log
- from PIL import Image
-
-
- #os.environ["CUDA_VISIBLE_DEVICES"] = "0"
- # Root directory of the project
- ROOT_DIR = os.getcwd()#得到该.py的绝对路径
-
- #ROOT_DIR = os.path.abspath("../")
- # Directory to save logs and trained model
- MODEL_DIR = os.path.join(ROOT_DIR, "logs")
-
- iter_num=0
-
- # Local path to trained weights file
- COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
- # Download COCO trained weights from Releases if needed
- if not os.path.exists(COCO_MODEL_PATH):
- utils.download_trained_weights(COCO_MODEL_PATH)
-
-
- class ShapesConfig(Config):
- """Configuration for training on the toy shapes dataset.
- Derives from the base Config class and overrides values specific
- to the toy shapes dataset.
- """
- # Give the configuration a recognizable name
- NAME = "shapes"
-
- # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
- # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
- GPU_COUNT = 1
- IMAGES_PER_GPU = 2
-
- # Number of classes (including background)
- NUM_CLASSES = 1 + 1 # background + 3 shapes
-
- # Use small images for faster training. Set the limits of the small side
- # the large side, and that determines the image shape.
- IMAGE_MIN_DIM = 320
- IMAGE_MAX_DIM = 384
-
- # Use smaller anchors because our image and objects are small
- RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6) # anchor side in pixels
-
- # Reduce training ROIs per image because the images are small and have
- # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
- TRAIN_ROIS_PER_IMAGE = 100
-
- # Use a small epoch since the data is simple
- STEPS_PER_EPOCH = 100
-
- # use small validation steps since the epoch is small
- VALIDATION_STEPS = 50
-
-
- config = ShapesConfig()
- config.display()
-
- class DrugDataset(utils.Dataset):
- # 得到该图中有多少个实例(物体)
- def get_obj_index(self, image):
- n = np.max(image)
- return n
-
- # 解析labelme中得到的yaml文件,从而得到mask每一层对应的实例标签
- 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']
- del labels[0]
- return labels
-
- # 重新写draw_mask
- def draw_mask(self, num_obj, mask, image,image_id):
- #print("draw_mask-->",image_id)
- #print("self.image_info",self.image_info)
- info = self.image_info[image_id]
- #print("info-->",info)
- #print("info[width]----->",info['width'],"-info[height]--->",info['height'])
- for index in range(num_obj):
- for i in range(info['width']):
- for j in range(info['height']):
- #print("image_id-->",image_id,"-i--->",i,"-j--->",j)
- #print("info[width]----->",info['width'],"-info[height]--->",info['height'])
- at_pixel = image.getpixel((i, j))
- if at_pixel == index + 1:
- mask[j, i, index] = 1
- return mask
-
- # 重新写load_shapes,里面包含自己的类别,可以任意添加
- # 并在self.image_info信息中添加了path、mask_path 、yaml_path
- # yaml_pathdataset_root_path = "/tongue_dateset/"
- # img_floder = dataset_root_path + "rgb"
- # mask_floder = dataset_root_path + "mask"
- # dataset_root_path = "/tongue_dateset/"
- def load_shapes(self, count, img_floder, mask_floder, imglist, dataset_root_path):
- """Generate the requested number of synthetic images.
- count: number of images to generate.
- height, width: the size of the generated images.
- """
- # Add classes,可通过这种方式扩展多个物体
- self.add_class("shapes", 1, "package") # 包裹
- for i in range(count):
- # 获取图片宽和高
-
- filestr = imglist[i].split(".")[0]
- #print(imglist[i],"-->",cv_img.shape[1],"--->",cv_img.shape[0])
- #print("id-->", i, " imglist[", i, "]-->", imglist[i],"filestr-->",filestr)
- #filestr = filestr.split("_")[1]
- mask_path = mask_floder + "/" + filestr + ".png"
- yaml_path = dataset_root_path + "labelme_json/" + filestr + "_json/info.yaml"
- print(dataset_root_path + "labelme_json/" + filestr + "_json/img.png")
- cv_img = cv2.imread(dataset_root_path + "labelme_json/" + filestr + "_json/img.png")
-
- self.add_image("shapes", image_id=i, path=img_floder + "/" + imglist[i],
- width=cv_img.shape[1], height=cv_img.shape[0], mask_path=mask_path, yaml_path=yaml_path)
-
- # 重写load_mask
- def load_mask(self, image_id):
- """Generate instance masks for shapes of the given image ID.
- """
- global iter_num
- print("image_id",image_id)
- info = self.image_info[image_id]
- count = 1 # number of object
- img = Image.open(info['mask_path'])
- num_obj = self.get_obj_index(img)
- mask = np.zeros([info['height'], info['width'], num_obj], dtype=np.uint8)
- mask = self.draw_mask(num_obj, mask, img,image_id)
- occlusion = np.logical_not(mask[:, :, -1]).astype(np.uint8)
- for i in range(count - 2, -1, -1):
- mask[:, :, i] = mask[:, :, i] * occlusion
-
- occlusion = np.logical_and(occlusion, np.logical_not(mask[:, :, i]))
- labels = []
- labels = self.from_yaml_get_class(image_id)
- labels_form = []
- for i in range(len(labels)):
- if labels[i].find("tank") != -1:
- # print "box"
- labels_form.append("tank")
- elif labels[i].find("triangle")!=-1:
- #print "column"
- labels_form.append("triangle")
- elif labels[i].find("white")!=-1:
- #print "package"
- labels_form.append("white")
- class_ids = np.array([self.class_names.index(s) for s in labels_form])
- return mask, class_ids.astype(np.int32)
-
- def get_ax(rows=1, cols=1, size=8):
- """Return a Matplotlib Axes array to be used in
- all visualizations in the notebook. Provide a
- central point to control graph sizes.
- Change the default size attribute to control the size
- of rendered images
- """
- _, ax = plt.subplots(rows, cols, figsize=(size * cols, size * rows))
- return ax
-
- #基础设置
- dataset_root_path="train_data/"#含有4个文件夹的主目录
- img_floder = dataset_root_path + "pic"
- mask_floder = dataset_root_path + "cv2_mask"
- #yaml_floder = dataset_root_path
- imglist = os.listdir(img_floder)
- count = len(imglist)
-
- #train与val数据集准备
- dataset_train = DrugDataset()
- dataset_train.load_shapes(count, img_floder, mask_floder, imglist,dataset_root_path)
- dataset_train.prepare()
-
- #print("dataset_train-->",dataset_train._image_ids)
-
- dataset_val = DrugDataset()
- dataset_val.load_shapes(7, img_floder, mask_floder, imglist,dataset_root_path)
- dataset_val.prepare()
-
- #print("dataset_val-->",dataset_val._image_ids)
-
- # Load and display random samples
- #image_ids = np.random.choice(dataset_train.image_ids, 4)
- #for image_id in image_ids:
- # image = dataset_train.load_image(image_id)
- # mask, class_ids = dataset_train.load_mask(image_id)
- # visualize.display_top_masks(image, mask, class_ids, dataset_train.class_names)
-
- # Create model in training mode
- model = modellib.MaskRCNN(mode="training", config=config,
- model_dir=MODEL_DIR)
-
- # Which weights to start with?
- init_with = "coco" # imagenet, coco, or last
-
- if init_with == "imagenet":
- model.load_weights(model.get_imagenet_weights(), by_name=True)
- elif init_with == "coco":
- # Load weights trained on MS COCO, but skip layers that
- # are different due to the different number of classes
- # See README for instructions to download the COCO weights
- model.load_weights(COCO_MODEL_PATH, by_name=True,
- exclude=["mrcnn_class_logits", "mrcnn_bbox_fc",
- "mrcnn_bbox", "mrcnn_mask"])
- elif init_with == "last":
- # Load the last model you trained and continue training
- model.load_weights(model.find_last()[1], by_name=True)
-
- # Train the head branches
- # Passing layers="heads" freezes all layers except the head
- # layers. You can also pass a regular expression to select
- # which layers to train by name pattern.
- model.train(dataset_train, dataset_val,
- learning_rate=config.LEARNING_RATE,
- epochs=20,
- layers='heads')
-
-
-
- # Fine tune all layers
- # Passing layers="all" trains all layers. You can also
- # pass a regular expression to select which layers to
- # train by name pattern.
- model.train(dataset_train, dataset_val,
- learning_rate=config.LEARNING_RATE / 10,
- epochs=40,
- layers="all")
训练的结果图:
3 在经过训练后,通过测试可以观察我们模型的效果,训练的次数比较少,效果一般。
测试代码如下图所示:
- # -*- coding: utf-8 -*-
- import os
- import sys
- import random
- import math
- import numpy as np
- import skimage.io
- import matplotlib
- import matplotlib.pyplot as plt
- import cv2
- import time
- from mrcnn.config import Config
- from datetime import datetime
- # Root directory of the project
- ROOT_DIR = os.getcwd()
-
- # Import Mask RCNN
- sys.path.append(ROOT_DIR) # To find local version of the library
- from mrcnn import utils
- import mrcnn.model as modellib
- from mrcnn import visualize
- # Import COCO config
- sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version
- from samples.coco import coco
-
-
- # Directory to save logs and trained model
- MODEL_DIR = os.path.join(ROOT_DIR, "logs")
-
- # Local path to trained weights file
- COCO_MODEL_PATH = os.path.join(MODEL_DIR ,"mask_rcnn_coco.h5")
- # Download COCO trained weights from Releases if needed
- if not os.path.exists(COCO_MODEL_PATH):
- utils.download_trained_weights(COCO_MODEL_PATH)
- print("cuiwei***********************")
-
- # Directory of images to run detection on
- IMAGE_DIR = os.path.join(ROOT_DIR, "images")
-
- class ShapesConfig(Config):
- """Configuration for training on the toy shapes dataset.
- Derives from the base Config class and overrides values specific
- to the toy shapes dataset.
- """
- # Give the configuration a recognizable name
- NAME = "shapes"
-
- # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
- # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
- GPU_COUNT = 1
- IMAGES_PER_GPU = 1
-
- # Number of classes (including background)
- NUM_CLASSES = 1 + 3 # background + 3 shapes
-
- # Use small images for faster training. Set the limits of the small side
- # the large side, and that determines the image shape.
- IMAGE_MIN_DIM = 320
- IMAGE_MAX_DIM = 384
-
- # Use smaller anchors because our image and objects are small
- RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6) # anchor side in pixels
-
- # Reduce training ROIs per image because the images are small and have
- # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
- TRAIN_ROIS_PER_IMAGE =100
-
- # Use a small epoch since the data is simple
- STEPS_PER_EPOCH = 100
-
- # use small validation steps since the epoch is small
- VALIDATION_STEPS = 50
-
- #import train_tongue
- #class InferenceConfig(coco.CocoConfig):
- class InferenceConfig(ShapesConfig):
- # Set batch size to 1 since we'll be running inference on
- # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
- GPU_COUNT = 1
- IMAGES_PER_GPU = 1
-
- config = InferenceConfig()
-
- model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
-
-
- # Create model object in inference mode.
- model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
-
- # Load weights trained on MS-COCO
- model.load_weights(COCO_MODEL_PATH, by_name=True)
-
- # COCO Class names
- # Index of the class in the list is its ID. For example, to get ID of
- # the teddy bear class, use: class_names.index('teddy bear')
- class_names = ['BG', 'package']
- # Load a random image from the images folder
- file_names = next(os.walk(IMAGE_DIR))[2]
- image = skimage.io.imread(os.path.join(IMAGE_DIR, random.choice(file_names)))
-
- a=datetime.now()
- # Run detection
- results = model.detect([image], verbose=1)
- b=datetime.now()
- # Visualize results
- print("shijian",(b-a).seconds)
- r = results[0]
- visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'],
- class_names, r['scores'])
参考博客:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。