糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 基于VS+OpenCV C++搭建NanoDet-Plus轻量级目标检测模型并训练(二)

基于VS+OpenCV C++搭建NanoDet-Plus轻量级目标检测模型并训练(二)

时间:2023-12-09 16:07:12

相关推荐

基于VS+OpenCV C++搭建NanoDet-Plus轻量级目标检测模型并训练(二)

1.数据准备

标签格式是json,分成训练集(train)和验证集(val),分别存放图和对应的标签文件,利用如下代码将单个的json文件转成coco格式的json,代码如下:

# -*- coding:utf-8 -*-import argparseimport jsonimport matplotlib.pyplot as pltimport skimage.io as iofrom labelme import utilsimport numpy as npimport globimport PIL.Imageclass MyEncoder(json.JSONEncoder):def default(self, obj):if isinstance(obj, np.integer):return int(obj)elif isinstance(obj, np.floating):return float(obj)elif isinstance(obj, np.ndarray):return obj.tolist()else:return super(MyEncoder, self).default(obj)class labelme2coco(object):def __init__(self, labelme_json=[], save_json_path='./tran.json'):self.labelme_json = labelme_jsonself.save_json_path = save_json_pathself.images = []self.categories = []self.annotations = []# self.data_coco = {}self.label = []self.annID = 1self.height = 0self.width = 0self.save_json()def data_transfer(self):for num, json_file in enumerate(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 in self.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 += 1def image(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]width = data['imageWidth']height = data['imageHeight']img = Noneimage['height'] = heightimage['width'] = widthimage['id'] = num + 1image['file_name'] = data['imagePath'].split('/')[-1]self.height = heightself.width = widthreturn imagedef categorie(self, label):categorie = {}categorie['supercategory'] = 'Cancer'categorie['id'] = len(self.label) + 1 # 0 默认为背景categorie['name'] = labelreturn categoriedef annotation(self, points, label, num):annotation = {}annotation['segmentation'] = [list(np.asarray(points).flatten())]annotation['iscrowd'] = 0annotation['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.annIDreturn annotationdef getcatid(self, label):for categorie in self.categories:if label == categorie['name']:return categorie['id']return 1def getbbox(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 = pointsmask = self.polygons_to_mask([self.height, self.width], polygons)return self.mask2box(mask)def mask2box(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格式def polygons_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)return maskdef data2coco(self):data_coco = {}data_coco['images'] = self.imagesdata_coco['categories'] = self.categoriesdata_coco['annotations'] = self.annotationsreturn data_cocodef save_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 更加美观显示labelme_json = glob.glob(r'./*.json')# labelme_json=['./1.json']labelme2coco(labelme_json, '.\\instances_train.json')

运行成功会在当前文件夹下生成一个很大的json文件,包含所有的标签信息,训练时就是读取这个文件。

2.修改配置文件

打开源码下的config文件夹,我这边选择的是nanodet-plus-m-1.5x_416.yml这个规格的网络,需要修改的部分如下:

# nanodet-plus-m-1.5x_416# COCO mAP(0.5:0.95) = 0.341# AP_50 = 0.506# AP_75 = 0.357# AP_small = 0.143#AP_m = 0.363#AP_l = 0.539save_dir: workspace/nanodet-plus-m-1.5x_416model:weight_averager:name: ExpMovingAveragerdecay: 0.9998arch:name: NanoDetPlusdetach_epoch: 10backbone:name: ShuffleNetV2model_size: 1.5xout_stages: [2,3,4]activation: LeakyReLUfpn:name: GhostPANin_channels: [176, 352, 704]out_channels: 128kernel_size: 5num_extra_level: 1use_depthwise: Trueactivation: LeakyReLUhead:name: NanoDetPlusHeadnum_classes: 80#自己的类别数input_channel: 128feat_channels: 128stacked_convs: 2kernel_size: 5strides: [8, 16, 32, 64]activation: LeakyReLUreg_max: 7norm_cfg:type: BNloss:loss_qfl:name: QualityFocalLossuse_sigmoid: Truebeta: 2.0loss_weight: 1.0loss_dfl:name: DistributionFocalLossloss_weight: 0.25loss_bbox:name: GIoULossloss_weight: 2.0# Auxiliary head, only use in training time.aux_head:name: SimpleConvHeadnum_classes: 80input_channel: 256feat_channels: 256stacked_convs: 4strides: [8, 16, 32, 64]activation: LeakyReLUreg_max: 7data:train:name: CocoDatasetimg_path: coco/train #这里需要修改成训练图片的文件夹路径ann_path: coco/annotations/instances_train.json#这里修改对应的标签文件input_size: [416,416] #[w,h]keep_ratio: Falsepipeline:perspective: 0.0scale: [0.6, 1.4]stretch: [[0.8, 1.2], [0.8, 1.2]]rotation: 0shear: 0translate: 0.2flip: 0.5brightness: 0.2contrast: [0.6, 1.4]saturation: [0.5, 1.2]normalize: [[103.53, 116.28, 123.675], [57.375, 57.12, 58.395]]val:name: CocoDatasetimg_path: coco/val#这里修改成验证集的文件夹路径ann_path: coco/annotations/instances_val.json#这里是对应的文件夹路径input_size: [416,416] #[w,h]keep_ratio: Falsepipeline:normalize: [[103.53, 116.28, 123.675], [57.375, 57.12, 58.395]]device:gpu_ids: [0]workers_per_gpu: 10batchsize_per_gpu: 96schedule:# resume:# load_model:optimizer:name: AdamWlr: 0.001weight_decay: 0.05warmup:name: linearsteps: 500ratio: 0.0001total_epochs: 300#总的迭代次数lr_schedule:name: CosineAnnealingLRT_max: 300eta_min: 0.00005val_intervals: 10grad_clip: 35evaluator:name: CocoDetectionEvaluatorsave_key: mAPlog:interval: 50#修改成自己的类别名class_names: ['person', 'bicycle', 'car', 'motorcycle', 'airplane', 'bus','train', 'truck', 'boat', 'traffic_light', 'fire_hydrant','stop_sign', 'parking_meter', 'bench', 'bird', 'cat', 'dog','horse', 'sheep', 'cow', 'elephant', 'bear', 'zebra', 'giraffe','backpack', 'umbrella', 'handbag', 'tie', 'suitcase', 'frisbee','skis', 'snowboard', 'sports_ball', 'kite', 'baseball_bat','baseball_glove', 'skateboard', 'surfboard', 'tennis_racket','bottle', 'wine_glass', 'cup', 'fork', 'knife', 'spoon', 'bowl','banana', 'apple', 'sandwich', 'orange', 'broccoli', 'carrot','hot_dog', 'pizza', 'donut', 'cake', 'chair', 'couch','potted_plant', 'bed', 'dining_table', 'toilet', 'tv', 'laptop','mouse', 'remote', 'keyboard', 'cell_phone', 'microwave','oven', 'toaster', 'sink', 'refrigerator', 'book', 'clock','vase', 'scissors', 'teddy_bear', 'hair_drier', 'toothbrush']

3.训练

输入如下命令即可开始训练

python tools/train.py CONFIG_FILE_PATH

训练过程会出一些小问题,我这总结了有以下:

1.安装的包的版本不对应导致报错

2.gpu显存不够,修改batchsize

3.电脑本身环境的问题

具体问题具体分析,有不当之处,欢迎一起交流学习~

4.训练过程可视化

训练过程中会在workspace文件夹下生成训练日志,通过tensorbord就可将训练过程可视化。结果如下:

如果觉得《基于VS+OpenCV C++搭建NanoDet-Plus轻量级目标检测模型并训练(二)》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。