Advertisement

seresnet50训练自己的数据集_使用mask scoring RCNN训练自己的数据集

阅读量:

本文主要参考下面两篇博文,并在部分细节处做了修改。

一、数据集准备

(训练集验证集测试集的数据分别准备)

1、标注数据集

大多数人会用labelme来标注数据集,然后用labelme将每张标注图片都生成一个json文件。labelme教程网上很多,这里不再赘述。

本人由于原图的标注目标很小,用labelme标注未免不精确,所以先用PS手动标注后再写代码把标注图转换成了labelme格式的json文件。

结果如图:

2、将这些json文件转换成coco格式

这一步我使用如下代码可成功转换。

#-- coding:utf-8 --

importos, sysimportargparseimportjsonimportmatplotlib.pyplot as pltimportskimage.io as iofrom labelme importutilsimportnumpy as npimportglobimportPIL.ImageclassMyEncoder(json.JSONEncoder):defdefault(self, obj):ifisinstance(obj, np.integer):returnint(obj)elifisinstance(obj, np.floating):returnfloat(obj)elifisinstance(obj, np.ndarray):returnobj.tolist()else:returnsuper(MyEncoder, self).default(obj)classlabelme2coco(object):def init(self, labelme_json=[], save_json_path='./tran.json'):''':param labelme_json: 所有labelme的json文件路径组成的列表

:param save_json_path: json保存位置'''self.labelme_json=labelme_json

self.save_json_path=save_json_path

self.images=[]

self.categories=[]

self.annotations=[]#self.data_coco = {}self.label=[]

self.annID= 1self.height=0

self.width=0

self.save_json()defdata_transfer(self):for num, json_file inenumerate(self.labelme_json):

with open(json_file,'r') as fp:

data= json.load(fp) #加载json文件self.images.append(self.image(data, num))for shapes in data['shapes']:

label= shapes['label']if label not inself.label:

self.categories.append(self.categorie(label))

self.label.append(label)

points= shapes['points'] #这里的point是用rectangle标注得到的,只有两个点,需要转成四个点points.append([points[0][0], points[1][1]])

points.append([points[1][0], points[0][1]])

self.annotations.append(self.annotation(points, label, num))

self.annID+= 1

defimage(self, data, num):

image={}#img = utils.img_b64_to_arr(data['imageData']) # 解析原图片数据

#img=io.imread(data['imagePath']) # 通过图片路径打开图片

#img = cv2.imread(data['imagePath'], 0)

#height, width = img.shape[:2]height= data['imageHeight']

width= data['imageWidth']

image['height'] =height

image['width'] =width

image['id'] = num + 1image['file_name'] = data['imagePath'].split('/')[-1]

self.height=height

self.width=widthreturnimagedefcategorie(self, label):

categorie={}

categorie['supercategory'] = 'Cancer'categorie['id'] = len(self.label) + 1 #0 默认为背景categorie['name'] =labelreturncategoriedefannotation(self, points, label, num):

annotation={}

annotation['segmentation'] =[list(np.asarray(points).flatten())]

annotation['iscrowd'] =0

annotation['image_id'] = num + 1

#annotation['bbox'] = str(self.getbbox(points)) # 使用list保存json文件时报错(不知道为什么)

#list(map(int,a[1:-1].split(','))) a=annotation['bbox'] 使用该方式转成listannotation['bbox'] =list(map(float, self.getbbox(points)))

annotation['area'] = annotation['bbox'][2] * annotation['bbox'][3]#annotation['category_id'] = self.getcatid(label)annotation['category_id'] = self.getcatid(label) #注意,源代码默认为1annotation['id'] =self.annIDreturnannotationdefgetcatid(self, label):for categorie inself.categories:if label == categorie['name']:return categorie['id']return 1

defgetbbox(self, points):#img = np.zeros([self.height,self.width],np.uint8)

#cv2.polylines(img, [np.asarray(points)], True, 1, lineType=cv2.LINE_AA) # 画边界线

#cv2.fillPoly(img, [np.asarray(points)], 1) # 画多边形 内部像素值为1polygons=points

mask=self.polygons_to_mask([self.height, self.width], polygons)returnself.mask2box(mask)defmask2box(self, mask):'''从mask反算出其边框

mask:[h,w] 0、1组成的图片

1对应对象,只需计算1对应的行列号(左上角行列号,右下角行列号,就可以算出其边框)'''

#np.where(mask==1)index= np.argwhere(mask == 1)

rows=index[:, 0]

clos= index[:, 1]#解析左上角行列号left_top_r= np.min(rows) #yleft_top_c= np.min(clos) #x

#解析右下角行列号right_bottom_r=np.max(rows)

right_bottom_c=np.max(clos)#return [(left_top_r,left_top_c),(right_bottom_r,right_bottom_c)]

#return [(left_top_c, left_top_r), (right_bottom_c, right_bottom_r)]

#return [left_top_c, left_top_r, right_bottom_c, right_bottom_r] # [x1,y1,x2,y2]

return [left_top_c, left_top_r, right_bottom_c -left_top_c,

right_bottom_r- left_top_r] #[x1,y1,w,h] 对应COCO的bbox格式

defpolygons_to_mask(self, img_shape, polygons):

mask= np.zeros(img_shape, dtype=np.uint8)

mask=PIL.Image.fromarray(mask)

xy=list(map(tuple, polygons))

PIL.ImageDraw.Draw(mask).polygon(xy=xy, outline=1, fill=1)

mask= np.array(mask, dtype=bool)returnmaskdefdata2coco(self):

data_coco={}

data_coco['images'] =self.images

data_coco['categories'] =self.categories

data_coco['annotations'] =self.annotationsreturndata_cocodefsave_json(self):

self.data_transfer()

self.data_coco=self.data2coco()#保存json文件json.dump(self.data_coco, open(self.save_json_path,'w'), indent=4, cls=MyEncoder) #indent=4 更加美观显示

if name == 'main':

src_folder= os.path.abspath(sys.argv[1])#load src - join jsonlabelme_json= glob.glob(src_folder + '/*.json')

labelme2coco(labelme_json, sys.argv[2])

在运行这个代码时,只有把所有需要的模块都安装在anaconda当时安装labelme的那个虚拟环境下才能运行成功。

二、环境搭建(linux)

1、创建pytorch环境

conda create --name maskrcnn_benchmark

source activate maskrcnn_benchmark#所有模块的安装都在此虚拟环境下

conda install ipython

pip install ninja yacs cython matplotlib pyqt5

conda install pytorch-nightly torchvision=0.2.1 cudatoolkit=9.0

上面的步骤执行完之后还要离线安装torch1.0.1。因为某种墙的存在,在线下载torch不太容易实现,国内镜像源又没有1.0.1这个版本。而经过博主长期的踩坑发现torch1.0.1和torchvision=0.2.1加上numpy1.17才是可用组合。这是torch1.0.1的下载链接: http://download.pytorch.org/whl/cu100/torch-1.0.1-cp36-cp36m-linux_x86_64.whl,建议直接迅雷下载。下载完成后,cd到模块所在目录然后pip install torch-1.0.1-cp36-cp36m-linux_x86_64.whl即可。(本人的python是3.6,请酌情修改下载链接)

2、安装cocoapi及apex

export INSTALL_DIR=$PWD#install pycocotoolsgit clone https://github.com/cocodataset/cocoapi.git

cd cocoapi/PythonAPI

python setup.py build_ext install#install apexcd $INSTALL_DIR

git clone https://github.com/NVIDIA/apex.git

cd apex

python setup.py install--cuda_ext --cpp_ext

3、编译模型代码

#install PyTorch Detection

cd $INSTALL_DIR#maskrcnn-benchmark#git clone https://github.com/facebookresearch/maskrcnn-benchmark.gitgit clone https://github.com/zjhuang22/maskscoring_rcnn

cd maskscoring_rcnn

python setup.py build develop

三、训练前的准备

1、数据和预训练模型准备

在下载的maskscoring_rcnn中新建一个datasets目录,可按如下结构放置你的json文件和原始图像

─ datasets

└── annotations

├── coco_train.json

└── coco_test.json

└── coco_train#该文件夹放置训练集的原始图像

└── coco_test #该文件夹放置测试集的原始图像

另外,maskscoring_rcnn的pretrained_models目录下需要放置R-101.pkl和R-50.pkl这两个预训练模型,如果服务器连了网,在开始训练模型之前会自动下载这两个模型,如果服务器没有网就需要手动下载放到pretrained_models下了。作者在GitHub也放了有这些模型的百度网盘链接。

2、修改参数

(1)修改 maskscoring_rcnn/configs 目录下的配置文件,选择其中的 e2e_ms_rcnn_R_50_FPN_1x.yaml训练脚本,修改如下:

MODEL:

META_ARCHITECTURE:"GeneralizedRCNN"WEIGHT:"catalog://ImageNetPretrained/MSRA/R-50"PRETRAINED_MODELS:'pretrained_models'DATASETS:

TRAIN: ("coco_train_xxx",) #1.设置训练验证集,名字可以随意起,和其他配置文件对应即可。

TEST: ("coco_val_xxx",)

……(省略数行)

SOLVER:

BASE_LR: 0.002 #设置基础学习率,原为0.02

WEIGHT_DECAY: 0.0001

STEPS: (60000, 80000)

MAX_ITER: 5000 #2.设置最大迭代次数,可根据图片数量酌情增减,改小也可以更快看到结果。原为90000

(2)修改 maskscoring_rcnn/maskrcnn_benchmark/config 下的 paths_catalog.py 文件:

DATASETS ={"coco_2014_train": ( "coco/train2014", "coco/annotations/instances_train2014.json",),"coco_2014_val": ("coco/val2014", "coco/annotations/instances_val2014.json"),"coco_2014_minival": ( "coco/val2014", "coco/annotations/instances_minival2014.json", ),"coco_2014_valminusminival": ("coco/val2014", "coco/annotations/instances_valminusminival2014.json", ),#添加自己的数据集路径信息,在相应的代码段后面添加两行即可

"coco_train_xxx": ("coco_mydata_train", "annotations/coco_mydata_train.json"),"coco_val_xxx": ("coco_mydata_test", "annotations/coco_mydata_test.json"),

}

(3)修改 maskscoring_rcnn/maskrcnn_benchmark/config 下的 defaults.py 配置文件:

Size of the smallest side of the image during training

_C.INPUT.MIN_SIZE_TRAIN = 800 # (800,)训练集中图片的最小边长,酌情修改

Maximum size of the side of the image during training

_C.INPUT.MAX_SIZE_TRAIN = 1333 #训练集中图片的最大边长,酌情修改

Size of the smallest side of the image during testing

_C.INPUT.MIN_SIZE_TEST = 800 #测试集中图片的最小边长,酌情修改

Maximum size of the side of the image during testing

_C.INPUT.MAX_SIZE_TEST = 1333 #测试集中图片的最大边长,酌情修改

……省略数行……

_C.MODEL.ROI_BOX_HEAD.NUM_CLASSES = 3 # 修改分类数量,coco对应81(80+1),注意1加的是背景

_C.SOLVER.BASE_LR= 0.005 #修改学习率,默认为0.001

_C.SOLVER.CHECKPOINT_PERIOD = 1000 #修改check point数量,根据需要自定义

_C.SOLVER.IMS_PER_BATCH = 1 #修改batch size,默认16,这个值要能整除训练集的图片数量

_C.TEST.IMS_PER_BATCH= 1 #修改test batch size,默认8,这个值要能整除测试集的图片数量

_C.OUTPUT_DIR= "models/" #设置模型保存路径(对应自定义文件夹)

四、开始训练

到maskscoring_rcnn所在目录下执行:

python tools/train_net.py --config-file configs/e2e_ms_rcnn_R_50_FPN_1x.yaml

python tools/test_net.py --config-file configs/e2e_ms_rcnn_R_50_FPN_1x.yaml

在models里面可以查看训练日志。

五、模型预测

1、修改maskscoring_rcnn/configs 路径下的对应的yaml文件的权重路径。

MODEL:

META_ARCHITECTURE:"GeneralizedRCNN"WEIGHT:"models/model_0005000.pth"# 训练好的模型路径

BACKBONE:

CONV_BODY:"R-50-FPN"OUT_CHANNELS:256

2、修改maskscoring_rcnn/demo 路径下的 predictor.py 文件,添加类别信息。这个文件在原来的demo目录下是没有的,从mask rcnn benchmark的demo文件下复制过来即可。

class COCODemo(object):

COCO categoriesforpretty print

CATEGORIES=["__background","cla_a",#根据自己的数据集修改类别信息"cla_b","cla_c",

]

3、在maskscoring_rcnn/demo 下新建 predict.py,用于预测。

#!/usr/bin/env python

coding=UTF-8import os, sys

import numpyasnp

import cv2frommaskrcnn_benchmark.config import cfgfrompredictor import COCODemo

#1.修改后的配置文件

config_file= "configs/e2e_ms_rcnn_R_50_FPN_1x.yaml"# 2.配置

cfg.merge_from_file(config_file) # merge配置文件

cfg.merge_from_list(["MODEL.MASK_ON", True]) # 打开mask开关

cfg.merge_from_list(["MODEL.DEVICE", "cuda"])# or设置为CPU ["MODEL.DEVICE", "cpu"]

#cfg.merge_from_list(["MODEL.DEVICE", "cpu"])

coco_demo=COCODemo(

cfg,

min_image_size=800,

confidence_threshold=0.5, # 3.设置置信度

)if name == 'main':

in_folder= './datasets/test_images/'out_folder= './datasets/test_images_out/'

ifnot os.path.exists(out_folder):

os.makedirs(out_folder)for file_name inos.listdir(in_folder):if not file_name.endswith(('jpg', 'png')):continue# load file

img_path=os.path.join(in_folder, file_name)

image=cv2.imread(img_path)

method1. 直接得到opencv图片结果

#predictions= coco_demo.run_on_opencv_image(image)

#save_path =os.path.join(out_folder, file_name)

#cv2.imwrite(save_path, predictions)

method2. 获取预测结果

predictions=coco_demo.compute_prediction(image)

top_predictions=coco_demo.select_top_predictions(predictions)

draw

img=coco_demo.overlay_boxes(image, top_predictions)

img=coco_demo.overlay_mask(img, predictions)

img=coco_demo.overlay_class_names(img, top_predictions)

save_path=os.path.join(out_folder, file_name)

cv2.imwrite(save_path, img)

print results

boxes=top_predictions.bbox.numpy()

labels= top_predictions.get_field("labels").numpy() #label =labelList[np.argmax(scores)]

scores= top_predictions.get_field("scores").numpy()

masks= top_predictions.get_field("mask").numpy()for i inrange(len(boxes)):

print('box:', i, 'label:', labels[i])

x1,y1,x2,y2= [round(x) for x in boxes[i]] # = map(int, boxes[i])

print('x1,y1,x2,y2:', x1,y1,x2,y2)

4、运行程序。

python demo/predict.py

在运行的过程中会报错找不到文件或者无法导入相关的库,此时把相应的文件从 mask rcnn benchmark 对应的文件夹复制过来即可。具体操作可参考:https://www.cnblogs.com/littleLittleTiger/p/12582747.html

成功截图如下

全部评论 (0)

还没有任何评论哟~