当前位置:   article > 正文

Mask Rcnn目标分割-训练自己数据集-详细步骤_maskrcnn训练自己的数据集

maskrcnn训练自己的数据集

本文接着介绍了Mask Rcnn目标分割算法如何训练自己数据集,对训练所需的文件以及训练代码进行详细的说明。

本文详细介绍在只有样本图片数据时,如果建立Mask Rcnn目标分割训练数据集的步骤。过程中用到的所有代码均已提供。

一、制作自己的数据集

1、labelme安装

自己的数据和上面数据的区别就在于没有.json标签文件,所以训练自己的数据关键步骤就是获取标签文件,制作标签需要用到labelme软件。我们在当前虚拟环境下直接安装:

activate py37_torch(这是我的虚拟环境)

pip install pyqt5 -i https://pypi.tuna.tsinghua.edu.cn/simple/

pip install labelme

安装好后,直接在命令行输入labelme就可以打开标注软件了

具体安装和使用方法可以参考以下链接

https://zhuanlan.zhihu.com/p/436614108

2、labelme制作标签

在labelme软件中打开图片所在文件夹,一次对图片边缘进行画点制作标签,并保存,每张图片的标签以.json文件保存在图片所在目录

标签保存到与图片同一路径下,对所有图片标注后,得到下面所示的数据集(每张图片下面为对应的标签.json文件)

3、将标签转换为coco数据集格式(一)(可直接进行第4步,这一步仅作为探索中间过程的记录

(1)单个json文件转换为coco格式

在利用mask rcnn进行自己的数据集训练时,数据集的格式要采用coco格式,所以利用labelme自带的json_to_dataset将自己的.json文件转换。该文件所在路径如下图所示:

打开json_to_dataset.py文件,对保存路径进行修改,修改为自己转换后的路径即可。

生成的文件夹下一共包含5个文件(这里缺少了一个yaml,后面会介绍如何获取yaml)

(2)批量转换

但是这样一个一个文件转太麻烦,因此我们需要写一个程序自动将所有.json文件一次性转换。

这里我写了一个批量转换的程序

My_json_to_dataset.py

  1. import argparse
  2. import base64
  3. import json
  4. import os
  5. import os.path as osp
  6. import imgviz
  7. import PIL.Image
  8. from labelme.logger import logger
  9. from labelme import utils
  10. import glob
  11. # 最前面加入导包
  12. import yaml
  13. def main():
  14. logger.warning(
  15. "This script is aimed to demonstrate how to convert the "
  16. "JSON file to a single image dataset."
  17. )
  18. logger.warning(
  19. "It won't handle multiple JSON files to generate a "
  20. "real-use dataset."
  21. )
  22. parser = argparse.ArgumentParser()
  23. ###############################################增加的语句##############################
  24. # parser.add_argument("json_file")
  25. parser.add_argument("--json_dir",default="D:/2021file/Biye/Mask_RCNN-master/samples/Mydata")
  26. ###############################################end###################################
  27. parser.add_argument("-o", "--out", default=None)
  28. args = parser.parse_args()
  29. ###############################################增加的语句##############################
  30. assert args.json_dir is not None and len(args.json_dir) > 0
  31. # json_file = args.json_file
  32. json_dir = args.json_dir
  33. if osp.isfile(json_dir):
  34. json_list = [json_dir] if json_dir.endswith('.json') else []
  35. else:
  36. json_list = glob.glob(os.path.join(json_dir, '*.json'))
  37. ###############################################end###################################
  38. for json_file in json_list:
  39. json_name = osp.basename(json_file).split('.')[0]
  40. out_dir = args.out if (args.out is not None) else osp.join(osp.dirname(json_file), json_name)
  41. ###############################################end###################################
  42. if not osp.exists(out_dir):
  43. os.makedirs(out_dir)
  44. data = json.load(open(json_file))
  45. imageData = data.get("imageData")
  46. if not imageData:
  47. imagePath = os.path.join(os.path.dirname(json_file), data["imagePath"])
  48. with open(imagePath, "rb") as f:
  49. imageData = f.read()
  50. imageData = base64.b64encode(imageData).decode("utf-8")
  51. img = utils.img_b64_to_arr(imageData)
  52. label_name_to_value = {"_background_": 0}
  53. for shape in sorted(data["shapes"], key=lambda x: x["label"]):
  54. label_name = shape["label"]
  55. if label_name in label_name_to_value:
  56. label_value = label_name_to_value[label_name]
  57. else:
  58. label_value = len(label_name_to_value)
  59. label_name_to_value[label_name] = label_value
  60. lbl, _ = utils.shapes_to_label(
  61. img.shape, data["shapes"], label_name_to_value
  62. )
  63. label_names = [None] * (max(label_name_to_value.values()) + 1)
  64. for name, value in label_name_to_value.items():
  65. label_names[value] = name
  66. lbl_viz = imgviz.label2rgb(
  67. lbl, imgviz.asgray(img), label_names=label_names, loc="rb"
  68. )
  69. PIL.Image.fromarray(img).save(osp.join(out_dir, "img.png"))
  70. utils.lblsave(osp.join(out_dir, "label.png"), lbl)
  71. PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, "label_viz.png"))
  72. with open(osp.join(out_dir, "label_names.txt"), "w") as f:
  73. for lbl_name in label_names:
  74. f.write(lbl_name + "\n")
  75. logger.info("Saved to: {}".format(out_dir))
  76. if __name__ == "__main__":
  77. main()

程序运行结果: 

最后每个json文件都生成了一个新的文件夹

Labelme版本不同生成的mask图片位数也不同,要求是8位的,检查一下生成的label.png图片位数,如果你的不是8位的,则需要进一步转化,我的生成的是8位的,所以这里不需要转换了。

4、将标签转换为coco数据集格式(二)

修改My_json_to_dataset.py,增加了生成yaml文件代码

上面说到,生成的文件夹里没有.yaml文件,于是对上面的My_json_to_dataset.py进行修改。

修改后的文件如下:

My_json_to_dataset.py

  1. import argparse
  2. import base64
  3. import json
  4. import os
  5. import os.path as osp
  6. import imgviz
  7. import PIL.Image
  8. from labelme.logger import logger
  9. from labelme import utils
  10. import glob
  11. # 最前面加入导包
  12. import yaml
  13. def main():
  14. logger.warning(
  15. "This script is aimed to demonstrate how to convert the "
  16. "JSON file to a single image dataset."
  17. )
  18. logger.warning(
  19. "It won't handle multiple JSON files to generate a "
  20. "real-use dataset."
  21. )
  22. parser = argparse.ArgumentParser()
  23. ###############################################增加的语句##############################
  24. # parser.add_argument("json_file")
  25. parser.add_argument("--json_dir",default="D:/2021file/Biye/Mask_RCNN-master/samples/Mydata")
  26. ###############################################end###################################
  27. parser.add_argument("-o", "--out", default=None)
  28. args = parser.parse_args()
  29. ###############################################增加的语句##############################
  30. assert args.json_dir is not None and len(args.json_dir) > 0
  31. # json_file = args.json_file
  32. json_dir = args.json_dir
  33. if osp.isfile(json_dir):
  34. json_list = [json_dir] if json_dir.endswith('.json') else []
  35. else:
  36. json_list = glob.glob(os.path.join(json_dir, '*.json'))
  37. ###############################################end###################################
  38. for json_file in json_list:
  39. json_name = osp.basename(json_file).split('.')[0]
  40. out_dir = args.out if (args.out is not None) else osp.join(osp.dirname(json_file), json_name)
  41. ###############################################end###################################
  42. if not osp.exists(out_dir):
  43. os.makedirs(out_dir)
  44. data = json.load(open(json_file))
  45. imageData = data.get("imageData")
  46. if not imageData:
  47. imagePath = os.path.join(os.path.dirname(json_file), data["imagePath"])
  48. with open(imagePath, "rb") as f:
  49. imageData = f.read()
  50. imageData = base64.b64encode(imageData).decode("utf-8")
  51. img = utils.img_b64_to_arr(imageData)
  52. label_name_to_value = {"_background_": 0}
  53. for shape in sorted(data["shapes"], key=lambda x: x["label"]):
  54. label_name = shape["label"]
  55. if label_name in label_name_to_value:
  56. label_value = label_name_to_value[label_name]
  57. else:
  58. label_value = len(label_name_to_value)
  59. label_name_to_value[label_name] = label_value
  60. lbl, _ = utils.shapes_to_label(
  61. img.shape, data["shapes"], label_name_to_value
  62. )
  63. label_names = [None] * (max(label_name_to_value.values()) + 1)
  64. for name, value in label_name_to_value.items():
  65. label_names[value] = name
  66. lbl_viz = imgviz.label2rgb(
  67. lbl, imgviz.asgray(img), label_names=label_names, loc="rb"
  68. )
  69. PIL.Image.fromarray(img).save(osp.join(out_dir, "img.png"))
  70. utils.lblsave(osp.join(out_dir, "label.png"), lbl)
  71. PIL.Image.fromarray(lbl_viz).save(osp.join(out_dir, "label_viz.png"))
  72. with open(osp.join(out_dir, "label_names.txt"), "w") as f:
  73. for lbl_name in label_names:
  74. f.write(lbl_name + "\n")
  75. logger.info("Saved to: {}".format(out_dir))
  76. #######
  77. #增加了yaml生成部分
  78. logger.warning('info.yaml is being replaced by label_names.txt')
  79. info = dict(label_names=label_names)
  80. with open(osp.join(out_dir, 'info.yaml'), 'w') as f:
  81. yaml.safe_dump(info, f, default_flow_style=False)
  82. logger.info('Saved to: {}'.format(out_dir))
  83. if __name__ == "__main__":
  84. main()

这时就有了yaml文件

5、将数据整理成模型认可的形式

首先我们建立train_data文件夹,里面新建四个文件夹,

cv2_mask、json、labelme_json、pic

json:labelme生成的json文件

labelme_json:My_json_to_dataset生成的文件夹

pic:原图

cv2_mask:My_json_to_datase生成文件夹中的png格式label文件

除了cv2_mask文件夹,其它三个文件夹的内容在前面已经都生成了,放入到对应文件夹下即可

6、生成cv2_mask文件内容

先别着急把生成的label.png图存到cv2_mask文件夹里面,在此之前,为了适应模型内部默认的路径格式,需要对label.png进行简单的重命名(否则就要去代码里边改,比较麻烦)。

比如我的原图叫KS001,那这个png的图就应该改成KS001.png,这里写了个脚本进行批量转换。

rename.py

  1. # 把label.png改名为原图名.png
  2. import os
  3. for root, dirs, names in os.walk("D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/labelme_json"): # 改成你自己的json文件夹所在的目录
  4. for dr in dirs:
  5. file_dir = os.path.join(root, dr)
  6. # print(dr)
  7. file = os.path.join(file_dir, 'label.png')
  8. # print(file)
  9. new_name = dr.split('_')[0] + '.png'
  10. new_file_name = os.path.join(file_dir, new_name)
  11. os.rename(file, new_file_name)

 运行完代码后发现文件夹下的图片名称已经得到了修改

将名称修改后的mask图放入cv2_mask文件夹中,这里同样写了个脚本进行批量复制:

creat_mask.py

  1. import os
  2. from shutil import copyfile
  3. for root, dirs, names in os.walk("D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/labelme_json"): # 改成你自己的json文件夹所在的目录
  4. for dr in dirs:
  5. file_dir = os.path.join(root, dr)
  6. print(dr)
  7. file = os.path.join(file_dir, dr+'.png')
  8. print(file)
  9. new_name = dr.split('_')[0] + '.png'
  10. new_file_name = os.path.join(file_dir, new_name)
  11. print(new_file_name)
  12. tar_root = 'D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/cv2_mask' # 目标路径
  13. tar_file = os.path.join(tar_root, new_name)
  14. copyfile(new_file_name, tar_file)

 运行:

 运行完发现cv2_mask文件夹下已经有了全部mask图

二、训练

准备好以上数据集,即可以开始进行训练了

Mytrain.py

  1. # -*- coding: utf-8 -*-
  2. import os
  3. import sys
  4. import random
  5. import math
  6. import re
  7. import time
  8. import numpy as np
  9. import cv2
  10. # import matplotlib
  11. # import matplotlib.pyplot as plt
  12. import tensorflow as tf
  13. from mrcnn.config import Config
  14. # import utils
  15. from mrcnn import model as modellib, utils
  16. from mrcnn import visualize
  17. import yaml
  18. from mrcnn.model import log
  19. from PIL import Image
  20. # os.environ["CUDA_VISIBLE_DEVICES"] = "0"
  21. # Root directory of the project
  22. ROOT_DIR = os.getcwd()
  23. # ROOT_DIR = os.path.abspath("../")
  24. # Directory to save logs and trained model
  25. MODEL_DIR = os.path.join(ROOT_DIR, "logs")
  26. iter_num = 0
  27. # Local path to trained weights file
  28. COCO_MODEL_PATH = os.path.join(ROOT_DIR, "mask_rcnn_coco.h5")
  29. # Download COCO trained weights from Releases if needed
  30. # if not os.path.exists(COCO_MODEL_PATH):
  31. # utils.download_trained_weights(COCO_MODEL_PATH)
  32. class ShapesConfig(Config):
  33. """Configuration for training on the toy shapes dataset.
  34. Derives from the base Config class and overrides values specific
  35. to the toy shapes dataset.
  36. """
  37. # Give the configuration a recognizable name
  38. NAME = "shapes"
  39. # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
  40. # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
  41. GPU_COUNT = 1
  42. IMAGES_PER_GPU = 1
  43. # Number of classes (including background)
  44. NUM_CLASSES = 2 + 1 # background + 1 shapes 注意这里我是2类,所以是2+1
  45. # Use small images for faster training. Set the limits of the small side
  46. # the large side, and that determines the image shape.
  47. IMAGE_MIN_DIM = 256
  48. IMAGE_MAX_DIM = 1024
  49. # Use smaller anchors because our image and objects are small
  50. # RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6) # anchor side in pixels
  51. RPN_ANCHOR_SCALES = (16 * 6, 32 * 6, 64 * 6, 128 * 6, 256 * 6) # 我的图片中目标比较大,所以我把anchor的尺寸也设置的大了一点
  52. # Reduce training ROIs per image because the images are small and have
  53. # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
  54. TRAIN_ROIS_PER_IMAGE = 100
  55. # Use a small epoch since the data is simple
  56. STEPS_PER_EPOCH = 50 # 每个epoch中迭代的step,最好不要改动
  57. # use small validation steps since the epoch is small
  58. VALIDATION_STEPS = 50
  59. config = ShapesConfig()
  60. config.display()
  61. class DrugDataset(utils.Dataset):
  62. # 得到该图中有多少个实例(物体)
  63. def get_obj_index(self, image):
  64. n = np.max(image)
  65. return n
  66. # 解析labelme中得到的yaml文件,从而得到mask每一层对应的实例标签
  67. def from_yaml_get_class(self, image_id):
  68. info = self.image_info[image_id]
  69. with open(info['yaml_path']) as f:
  70. #temp = yaml.load(f.read())
  71. temp = yaml.load(f.read(),Loader=yaml.FullLoader)
  72. labels = temp['label_names']
  73. del labels[0]
  74. return labels
  75. # 重新写draw_mask
  76. def draw_mask(self, num_obj, mask, image, image_id):
  77. # print("draw_mask-->",image_id)
  78. # print("self.image_info",self.image_info)
  79. info = self.image_info[image_id]
  80. # print("info-->",info)
  81. # print("info[width]----->",info['width'],"-info[height]--->",info['height'])
  82. for index in range(num_obj):
  83. for i in range(info['width']):
  84. for j in range(info['height']):
  85. # print("image_id-->",image_id,"-i--->",i,"-j--->",j)
  86. # print("info[width]----->",info['width'],"-info[height]--->",info['height'])
  87. at_pixel = image.getpixel((i, j))
  88. if at_pixel == index + 1:
  89. mask[j, i, index] = 1
  90. return mask
  91. # 重新写load_shapes,里面包含自己的自己的类别
  92. # 并在self.image_info信息中添加了path、mask_path 、yaml_path
  93. # yaml_pathdataset_root_path = "/dateset/"
  94. # img_floder = dataset_root_path + "rgb"
  95. # mask_floder = dataset_root_path + "mask"
  96. # dataset_root_path = "/tongue_dateset/"
  97. def load_shapes(self, count, img_floder, mask_floder, imglist, dataset_root_path):
  98. """Generate the requested number of synthetic images.
  99. count: number of images to generate.
  100. height, width: the size of the generated images.
  101. """
  102. # Add classes
  103. self.add_class("shapes", 1, "KS")
  104. self.add_class("shapes", 2, "MS")
  105. # self.add_class("shapes", 3, "leibie3")
  106. # self.add_class("shapes", 4, "leibie4")
  107. for i in range(count):
  108. # 获取图片宽和高
  109. print(i)
  110. filestr = imglist[i].split(".")[0]
  111. # print(imglist[i],"-->",cv_img.shape[1],"--->",cv_img.shape[0])
  112. # print("id-->", i, " imglist[", i, "]-->", imglist[i],"filestr-->",filestr)
  113. # filestr = filestr.split("_")[1]
  114. mask_path = mask_floder + "/" + filestr + ".png"
  115. yaml_path = dataset_root_path + "labelme_json/" + filestr + "/info.yaml"
  116. print(dataset_root_path + "labelme_json/" + filestr + "/img.png")
  117. cv_img = cv2.imread(dataset_root_path + "labelme_json/" + filestr + "/img.png")
  118. print(type(cv_img))
  119. self.add_image("shapes", image_id=i, path=img_floder + "/" + imglist[i],
  120. width=cv_img.shape[1], height=cv_img.shape[0], mask_path=mask_path, yaml_path=yaml_path)
  121. # 重写load_mask
  122. def load_mask(self, image_id):
  123. """Generate instance masks for shapes of the given image ID.
  124. """
  125. global iter_num
  126. print("image_id", image_id)
  127. info = self.image_info[image_id]
  128. count = 1 # number of object
  129. img = Image.open(info['mask_path'])
  130. num_obj = self.get_obj_index(img)
  131. mask = np.zeros([info['height'], info['width'], num_obj], dtype=np.uint8)
  132. mask = self.draw_mask(num_obj, mask, img, image_id)
  133. occlusion = np.logical_not(mask[:, :, -1]).astype(np.uint8)
  134. for i in range(count - 2, -1, -1):
  135. mask[:, :, i] = mask[:, :, i] * occlusion
  136. occlusion = np.logical_and(occlusion, np.logical_not(mask[:, :, i]))
  137. labels = []
  138. labels = self.from_yaml_get_class(image_id)
  139. labels_form = []
  140. for i in range(len(labels)):
  141. if labels[i].find("KS") != -1:
  142. labels_form.append("KS")
  143. elif labels[i].find("MS") != -1:
  144. labels_form.append("MS")
  145. # elif labels[i].find("leibie3") != -1:
  146. # labels_form.append("leibie3")
  147. # elif labels[i].find("leibie4") != -1:
  148. # labels_form.append("leibie4")
  149. class_ids = np.array([self.class_names.index(s) for s in labels_form])
  150. return mask, class_ids.astype(np.int32)
  151. '''
  152. def get_ax(rows=1, cols=1, size=8):
  153. """Return a Matplotlib Axes array to be used in
  154. all visualizations in the notebook. Provide a
  155. central point to control graph sizes.
  156. Change the default size attribute to control the size
  157. of rendered images
  158. """
  159. _, ax = plt.subplots(rows, cols, figsize=(size * cols, size * rows))
  160. return ax
  161. '''
  162. # 基础设置
  163. dataset_root_path = "D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/" # 你的数据的路径
  164. img_floder = dataset_root_path + "pic"
  165. mask_floder = dataset_root_path + "cv2_mask"
  166. # yaml_floder = dataset_root_path
  167. imglist = os.listdir(img_floder)
  168. count = len(imglist)
  169. # train与val数据集准备
  170. dataset_train = DrugDataset()
  171. dataset_train.load_shapes(count, img_floder, mask_floder, imglist, dataset_root_path)
  172. dataset_train.prepare()
  173. # print("dataset_train-->",dataset_train._image_ids)
  174. dataset_val = DrugDataset()
  175. dataset_val.load_shapes(count, img_floder, mask_floder, imglist, dataset_root_path)
  176. dataset_val.prepare()
  177. # print("dataset_val-->",dataset_val._image_ids)
  178. # Load and display random samples
  179. # image_ids = np.random.choice(dataset_train.image_ids, 4)
  180. # for image_id in image_ids:
  181. # image = dataset_train.load_image(image_id)
  182. # mask, class_ids = dataset_train.load_mask(image_id)
  183. # visualize.display_top_masks(image, mask, class_ids, dataset_train.class_names)
  184. # Create model in training mode
  185. model = modellib.MaskRCNN(mode="training", config=config,
  186. model_dir=MODEL_DIR)
  187. # Which weights to start with?
  188. init_with = "coco" # imagenet, coco, or last
  189. if init_with == "imagenet":
  190. model.load_weights(model.get_imagenet_weights(), by_name=True)
  191. elif init_with == "coco":
  192. # Load weights trained on MS COCO, but skip layers that
  193. # are different due to the different number of classes
  194. # See README for instructions to download the COCO weights
  195. # print(COCO_MODEL_PATH)
  196. model.load_weights(COCO_MODEL_PATH, by_name=True,
  197. exclude=["mrcnn_class_logits", "mrcnn_bbox_fc",
  198. "mrcnn_bbox", "mrcnn_mask"])
  199. elif init_with == "last":
  200. # Load the last model you trained and continue training
  201. model.load_weights(model.find_last()[1], by_name=True)
  202. # Train the head branches
  203. # Passing layers="heads" freezes all layers except the head
  204. # layers. You can also pass a regular expression to select
  205. # which layers to train by name pattern.
  206. model.train(dataset_train, dataset_val,
  207. learning_rate=config.LEARNING_RATE,
  208. epochs=10,
  209. layers='heads') # 固定其他层,只训练head,epoch为10
  210. # Fine tune all layers
  211. # Passing layers="all" trains all layers. You can also
  212. # pass a regular expression to select which layers to
  213. # train by name pattern.
  214. model.train(dataset_train, dataset_val,
  215. learning_rate=config.LEARNING_RATE / 10,
  216. epochs=10,
  217. layers="all") # 微调所有层的参数,epoch为10

代码中部分数据相关描述需要修改成你自己的数据描述

(1)首先修改数据集路径:

修改类别名称,定位到def load_shapes   120行,加入数据集中的类别

(2)定位到NUM_CLASSES,55行

修改为对应的类别数,注意要在类别数上+1,这里认为背景为一类

    # Number of classes (including background)

    NUM_CLASSES = 2 + 1  # background + 1 shapes  注意这里我是2类,所以是2+1

(3)定位到def load_mask,其中的类别也要做相应修改

(4)正常运行,开始训练

训练过程日志以及权重保存在logs中的最新一个文件夹中,同样可以使用tensorboard对训练过程进行查看

tensorboard --logdir="D:/2021file/Biye/Mask_RCNN-master/logs/shapes20220417T2356"

运行后在浏览器打开下面地址:(有时候运行框给我的地址是http://ComputerDing:6006,并不可用,所以我直接手动进入下面地址 )

http://localhost:6006/

四、训练时可能出现的报错及解决方法

1、报错:

AttributeError: 'NoneType' object has no attribute 'shape'

报错原因是没有找到文件,仔细一看它输出的文件路径和我的实际的有一点不一样,我的是

D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/labelme_json/KS001/img.png

它的是

D:/2021file/Biye/Mask_RCNN-master/samples/Mydata/train_data/labelme_json/KS001_json/img.png

解决方法:

注意这里三处都要修改过来

2、报错:

OSError: Unable to open file (unable to open file: name = 'D:\2021file\Biye\Mask_RCNN-master\mask_rcnn_coco.h5', errno = 2, error message = 'No such file or directory', flags = 0, o_flags = 0)

将下载的mask_rcnn_coco.h5权重文件放到'D:\2021file\Biye\Mask_RCNN-master目录下即可

3、报错:TypeError: load() missing 1 required positional argument: 'Loader'

原因分析:

由于Yaml 5.1版本后弃用了 yaml.load(file) 这个用法。Yaml 5.1版本之后就修改了需要指定Loader,通过默认加载器(FullLoader)禁止执行任意函数,使得此load函数的安全得到加强。

解决方法:

temp = yaml.load(f.read())

替换为:

temp = yaml.load(f.read(),Loader=yaml.FullLoader)

4、报错:IndexError: boolean index did not match indexed array along dimension 0; dimension is 0 but corresponding boolean dimension is 1

原因分析:自己数据集的类别没有在程序中加入

定位到def load_shapes   120行,加入数据集中的类别

注意def load_mask中的类别也要做相应修改

5、报错:ValueError: Error when checking input: expected input_image_meta to have shape (17,) but got array with shape (15,)

原因分析:报这个错误,应该是你的类别数忘记修改过来了

    # Number of classes (including background)

NUM_CLASSES = 2 + 1  # background + 1 shapes  注意这里我是2类,所以是2+1

五、测试

Mytest.py

  1. # -*- coding: utf-8 -*-
  2. import os
  3. import sys
  4. import random
  5. import math
  6. import numpy as np
  7. import skimage.io
  8. import matplotlib
  9. import matplotlib.pyplot as plt
  10. import cv2
  11. import time
  12. from mrcnn.config import Config
  13. from datetime import datetime
  14. # Root directory of the project
  15. ROOT_DIR = os.getcwd()
  16. # Import Mask RCNN
  17. sys.path.append(ROOT_DIR) # To find local version of the library
  18. from mrcnn import utils
  19. import mrcnn.model as modellib
  20. from mrcnn import visualize
  21. # Import COCO config
  22. # sys.path.append(os.path.join(ROOT_DIR, "samples/coco/")) # To find local version
  23. # from samples.coco import coco
  24. # Directory to save logs and trained model
  25. MODEL_DIR = os.path.join(ROOT_DIR, "logs")
  26. # Local path to trained weights file
  27. COCO_MODEL_PATH = "D:/2021file/Biye\Mask_RCNN-master/logs/shapes20220417T2356/mask_rcnn_shapes_0010.h5" # 模型保存目录
  28. # Download COCO trained weights from Releases if needed
  29. if not os.path.exists(COCO_MODEL_PATH):
  30. utils.download_trained_weights(COCO_MODEL_PATH)
  31. print("***********************")
  32. # Directory of images to run detection on
  33. #随机检测时用
  34. #IMAGE_DIR = os.path.join(ROOT_DIR, "images")
  35. class ShapesConfig(Config):
  36. """Configuration for training on the toy shapes dataset.
  37. Derives from the base Config class and overrides values specific
  38. to the toy shapes dataset.
  39. """
  40. # Give the configuration a recognizable name
  41. NAME = "shapes"
  42. # Train on 1 GPU and 8 images per GPU. We can put multiple images on each
  43. # GPU because the images are small. Batch size is 8 (GPUs * images/GPU).
  44. GPU_COUNT = 1
  45. IMAGES_PER_GPU = 1
  46. # Number of classes (including background)
  47. NUM_CLASSES = 2 + 1 # background + 2 shapes
  48. # Use small images for faster training. Set the limits of the small side
  49. # the large side, and that determines the image shape.
  50. IMAGE_MIN_DIM = 320
  51. IMAGE_MAX_DIM = 384
  52. # Use smaller anchors because our image and objects are small
  53. RPN_ANCHOR_SCALES = (8 * 6, 16 * 6, 32 * 6, 64 * 6, 128 * 6) # anchor side in pixels
  54. # Reduce training ROIs per image because the images are small and have
  55. # few objects. Aim to allow ROI sampling to pick 33% positive ROIs.
  56. TRAIN_ROIS_PER_IMAGE = 100
  57. # Use a small epoch since the data is simple
  58. STEPS_PER_EPOCH = 50
  59. # use small validation steps since the epoch is small
  60. VALIDATION_STEPS = 50
  61. # import train_tongue
  62. # class InferenceConfig(coco.CocoConfig):
  63. class InferenceConfig(ShapesConfig):
  64. # Set batch size to 1 since we'll be running inference on
  65. # one image at a time. Batch size = GPU_COUNT * IMAGES_PER_GPU
  66. GPU_COUNT = 1
  67. IMAGES_PER_GPU = 1
  68. config = InferenceConfig()
  69. model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
  70. # Create model object in inference mode.
  71. model = modellib.MaskRCNN(mode="inference", model_dir=MODEL_DIR, config=config)
  72. # Load weights trained on MS-COCO
  73. model.load_weights(COCO_MODEL_PATH, by_name=True)
  74. # COCO Class names
  75. # Index of the class in the list is its ID. For example, to get ID of
  76. # the teddy bear class, use: class_names.index('teddy bear')
  77. # 注意修改类别名称
  78. class_names = ['BG','KS', 'MS']
  79. # Load a random image from the images folder
  80. #有两种方式,一种是从文件夹中随机读取图片,另一种是指定图片路径
  81. #file_names = next(os.walk(IMAGE_DIR))[2]
  82. image = skimage.io.imread("F:/jk/KS/22_Color.png") # 你想要测试的图片
  83. a = datetime.now()
  84. # Run detection
  85. results = model.detect([image], verbose=1)
  86. b = datetime.now()
  87. # Visualize results
  88. print("Dec_time:", (b - a).seconds)
  89. r = results[0]
  90. #print(r)
  91. visualize.display_instances(image, r['rois'], r['masks'], r['class_ids'],
  92. class_names, r['scores'])

需修改以下地方

(1)训练得到的模型文件***.h5路径

(2)类别数

(3)类别名称(注意加上背景BG)

检测图片路径

若报错:IndexError: list index out of range

原因是类别名称里面忘记加了背景

(4)运行测试结果

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/300403
推荐阅读
相关标签
  

闽ICP备14008679号