赞
踩
yolo-obj.cfg
配置文件将 yolov4-custom.cfg
中的内容复制到 yolo-obj.cfg
里面,并做以下修改:
1.修改batch=64
,修改subdivisions=32
(这里根据自己的显卡设置合适参数,显存不足时可以把batch=
调小,或者subdivisions
调大)
2.修改max_batches=classes*2000
例如有2个类别人和车 ,那么就设置为4000,N个类就设置为N乘以2000
3.修改steps
为80%
到 90%
的max_batches
值,比如max_batches=4000,则steps=3200,3600
4.修改classes
,先用ctrl+F
搜索 [yolo
] 可以搜到3次,每次搜到的内容中 修改classes=你自己的类别 比如classes=2
5.修改filters
,一样先搜索 [yolo
] ,每次搜的yolo上一个[convolution] 中 filters=(classes + 5)x3
,比如filters=21
6.(可以跳过)如果要用[Gaussian_yolo] ,则搜索[Gaussian_yolo] 将[filters=57] 的filter 修改为 filters=(classes + 9)x3 (这里我没有修改)
obj.names
在主目录下创建obj.names
文件:
内容为你的类别,比如人和车,那么obj.names
为如下,多个类别依次往下写
person
car
obj.data
在主目录下创建obj.data
文件,内容如下:
classes= 2
train = ./scripts/2007_train.txt
valid = ./scripts/2007_val.txt
names = Release\obj.names
backup = backup/
其中class
为自己的类别个数;
train、valid、names
根据自己的路径修改,找不到的话,可以修改为自己的绝对路径;
backup
为权重保存的位置(需要提前创建好文件夹)
在scripts文件夹下按如下目录创建VOCdevkit 文件夹,放自己的训练数据,层级结构如下所示:
VOCdevkit
--VOC2007
----Annotations #(放XML标签文件)
----ImageSets
------Main
----JPEGImages # (放原始图片)
make_data.py
并运行主目录下创建make_data.py
文件,把如下代码方进去。运行此文件在scripts 文件下生成 3个相应的txt文件,在Main 下生成四个txt文件。
make_data.py
内容为:
import os import random import sys root_path = './scripts/VOCdevkit/VOC2007' xmlfilepath = root_path + '/Annotations' txtsavepath = root_path + '/ImageSets/Main' if not os.path.exists(root_path): print("cannot find such directory: " + root_path) os.makedirs(root_path) exit() if not os.path.exists(txtsavepath): os.makedirs(txtsavepath) trainval_percent = 0.9 train_percent = 0.9 total_xml = os.listdir(xmlfilepath) num = len(total_xml) list = range(num) tv = int(num * trainval_percent) tr = int(tv * train_percent) trainval = random.sample(list, tv) train = random.sample(trainval, tr) print("train and val size:", tv) print("train size:", tr) ftrainval = open(txtsavepath + '/trainval.txt', 'w') ftest = open(txtsavepath + '/test.txt', 'w') ftrain = open(txtsavepath + '/train.txt', 'w') fval = open(txtsavepath + '/val.txt', 'w') for i in list: name = total_xml[i][:-4] + '\n' if i in trainval: ftrainval.write(name) if i in train: ftrain.write(name) else: fval.write(name) else: ftest.write(name) ftrainval.close() ftrain.close() fval.close() ftest.close()
运行后会生成:
voc_label.py
并运行scripts
文件夹下有voc_label.py
,打开后修改自己的类别信息:
sets=[ (‘2007’, ‘train’), (‘2007’, ‘val’), (‘2007’, ‘test’)]
classes = [“person”,“car” ]
按自己的类别修改,但是顺序要和obj.name
保持一致:
# -*- coding:utf-8 -*- import xml.etree.ElementTree as ET import pickle import os from os import listdir, getcwd from os.path import join sets = [('2007', 'train'), ('2007', 'val'), ('2007', 'test')] classes = ["person", "car"] # 设置错误标签的log输出位置 write_path = open(r'D:\error.txt', 'w') def convert(size, box): dw = 1. / (size[0]) dh = 1. / (size[1]) x = (box[0] + box[1]) / 2.0 - 1 y = (box[2] + box[3]) / 2.0 - 1 w = box[1] - box[0] h = box[3] - box[2] x = x * dw w = w * dw y = y * dh h = h * dh return (x, y, w, h) def convert_annotation(year, image_id): in_file = open('D:/yolov4/mybuild/Release/scripts/VOCdevkit/VOC%s/Annotations/%s.xml' % (year, image_id), encoding="utf-8") out_file = open('D:/yolov4/mybuild/Release/scripts/VOCdevkit/VOC%s/labels/%s.txt' % (year, image_id), 'w', encoding="utf-8") #这里根据自己的路径修改 tree = ET.parse(in_file) root = tree.getroot() size = root.find('size') w = int(size.find('width').text) h = int(size.find('height').text) for obj in root.iter('object'): # difficult = obj.find('difficult').text cls = obj.find('name').text # if cls not in classes or int(difficult) == 1: # continue # print(in_file) # 标签自查 if cls not in classes: print(in_file, cls) write_path.write('%s.xml' % image_id +' '+ cls +'\n') continue else: cls_id = classes.index(cls) xmlbox = obj.find('bndbox') b = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text)) bb = convert((w, h), b) out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n') wd = getcwd() for year, image_set in sets: if not os.path.exists('VOCdevkit/VOC%s/labels/' % (year)): os.makedirs('VOCdevkit/VOC%s/labels/' % (year)) image_ids = open('VOCdevkit/VOC%s/ImageSets/Main/%s.txt' % (year, image_set)).read().strip().split() list_file = open('%s_%s.txt' % (year, image_set), 'w') for image_id in image_ids: list_file.write('%s/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n' % (wd, year, image_id)) convert_annotation(year, image_id) list_file.close() os.system("cat 2007_train.txt 2007_val.txt 2012_train.txt 2012_val.txt > train.txt") os.system("cat 2007_train.txt 2007_val.txt 2007_test.txt 2012_train.txt 2012_val.txt > train.all.txt")
运行后,在VOC2007文件下生成labels文件,文件夹里包含相应的txt.(现在voc2007文件里多出一个labels 文件夹)
首先下载预训练权重yolov4.conv.137,放入主目录下;
之后用下面的命令开始训练:
darknet.exe detector train obj.data yolo-obj.cfg yolov4.conv.137 -map
断点续训操作
darknet.exe detector train obj.data yolo-obj.cfg backup/yolo-obj_2000.weights -map
修改obj.data
valid = ./scripts/2007_test.txt
#valid = ./scripts/2007_val.txt
通过下面命令进行模型性能测试:
darknet detector map obj.data yolo-obj.cfg backup/yolo-obj_final.weights
这里提供一个yolov4批量测试脚本,脚本利用了opencv cuda进行了加速:
import numpy as np import time import cv2 import os class YOLOV4_Detection(): def __init__(self,coco_name_path,weights_path,cfg_path): self.coco_name_path=coco_name_path self.weights_path=weights_path self.cfg_path=cfg_path def yolov4_test(self,test_images,test_results): self.LABELS = open(self.coco_name_path,encoding="utf-8",errors="ignore").read().strip().split("\n") np.random.seed(666) #COLORS = np.random.randint(0, 255, size=(len(LABELS), 3), dtype="uint8") # 导入 YOLO 配置和权重文件并加载网络: print(self.cfg_path,self.weights_path) self.net = cv2.dnn.readNetFromDarknet(self.cfg_path, self.weights_path) #如果没有编译cuda版的opencv注释以下两行 self.net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) self.net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) # 获取 YOLO 未连接的输出图层 self.layer = self.net.getUnconnectedOutLayersNames() files=os.listdir(test_images) for filename in files: image=cv2.imread(os.path.join(test_images,filename)) # 获取图片尺寸 (H, W) = image.shape[:2] # 从输入图像构造一个 blob,然后执行 YOLO 对象检测器的前向传递,给我们边界盒和相关概率 blob = cv2.dnn.blobFromImage(image, 1/255.0, (608, 608), swapRB=True, crop=False) self.net.setInput(blob) start = time.time() # 前向传递,获得信息 layerOutputs = self.net.forward(self.layer) # 用于得出检测时间 boxes = [] confidences = [] classIDs = [] # 循环提取每个输出层 for output in layerOutputs: # 循环提取每个框 for detection in output: # 提取当前目标的类 ID 和置信度 scores = detection[5:] classID = np.argmax(scores) confidence = scores[classID] # 通过确保检测概率大于最小概率来过滤弱预测 if confidence > 0.5: # 将边界框坐标相对于图像的大小进行缩放,YOLO 返回的是边界框的中心(x, y)坐标, # 后面是边界框的宽度和高度 box = detection[0:4] * np.array([W, H, W, H]) (centerX, centerY, width, height) = box.astype("int") # 转换出边框左上角坐标 x = int(centerX - (width / 2)) y = int(centerY - (height / 2)) # 更新边界框坐标、置信度和类 id 的列表 boxes.append([x, y, int(width), int(height)]) confidences.append(float(confidence)) classIDs.append(classID) # 非最大值抑制,确定唯一边框 idxs = cv2.dnn.NMSBoxes(boxes, confidences, 0.5, 0.3) # 确定每个对象至少有一个框存在 if len(idxs) > 0: # 循环画出保存的边框 for i in idxs.flatten(): # 提取坐标和宽度 (x, y) = (boxes[i][0], boxes[i][1]) (w, h) = (boxes[i][2], boxes[i][3]) # 画出边框和标签 #color = [int(c) for c in COLORS[classIDs[i]]] color_rectangele=[0,255,0] color_text=[0,0,255] cv2.rectangle(image, (x, y), (x + w, y + h), color_rectangele, 2, lineType=cv2.LINE_AA) text = "{}: {:.4f}".format(self.LABELS[classIDs[i]], confidences[i]) cv2.putText(image, text, (x, y - 5), cv2.FONT_HERSHEY_SIMPLEX, 1.5, color_text, 2, lineType=cv2.LINE_AA) end = time.time() print("YOLO took {:.6f} seconds".format(end - start)) cv2.imwrite(os.path.join(test_results,filename),image) coco_name_path=r"D:\yolov4\mybuild\Release\test\obj.names" weights_path=r"D:\yolov4\mybuild\Release\test\yolo-obj_best.weights" cfg_path=r"D:\yolov4\mybuild\Release\test\yolo-obj.cfg" test_images=r"D:\yolov4\mybuild\Release\test\testimg" test_results=r"D:\yolov4\mybuild\Release\test\output" #net = cv2.dnn.readNetFromDarknet(cfg_path, weights_path) #net.setPreferableBackend(cv2.dnn.DNN_BACKEND_CUDA) #net.setPreferableTarget(cv2.dnn.DNN_TARGET_CUDA) test1=YOLOV4_Detection(coco_name_path,weights_path,cfg_path) test1.yolov4_test(test_images,test_results)
参考文档:https://blog.csdn.net/weixin_41444791/article/details/107761115
如果阅读本文对你有用,欢迎关注点赞评论收藏呀!!!
2021年3月29日11:49:31
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。