在本文章你可以学习到如何训练自己采集的数据集,生成模型,并用yolo v3算法实现交通标志识别。当然交通标志可以是其他比如交通灯、车辆、行人等等。
效果图:
环境:win10+python3.6 +keras +Tensorflow 1.14.0+Pycharm2019
python环境我建议下载anaconda,anaconda内置python 3.6解释器,其他python版本不用单独安装,十分便捷,在安装
anaconda的python解释器自带的下载源下载东西很慢,因此可以改为国内豆瓣或者清华等镜像源。
这里教大家改为豆瓣源。
可以看我的另外一篇文章:
首先明确进行yolov3训练数据集的格式,如下:
文件的绝对路径 left,top,right,bottom,类别编号
其实所有模型方法进行训练的时候甚至机器学习svm分类等,都是要告诉电脑(以检测猫来说),你的图片在计算机存储的路径;你的图片中猫目标的位置,即left,top,right,bottom ;以及猫类别的编号。
实际例子:
/home/matthew/VOC2007/JPEGImages/000000160.jpg 186,192,353,349,0 579,286,850,500,0/home/matthew/VOC2007/JPEGImages/000000162.jpg 403,22,458,60,0 400,245,552,389,0 432,0,459,12,0 926,1,999,15,0/home/matthew/VOC2007/JPEGImages/000000166.jpg 146,246,340,428,0
可以看到数据中不只有一个目标。
那么这么标准的数据如何得到呢,其实可以用一个深度学习训练图片的打标签工具——labelImg。关于这个软件的安装与使用见链接:
图像识别中标注工具labelImg的安装和使用——深度学习打标签
这个软件会使用会生成标准xml文件,然后经过下面一系列操作,最后成为txt文件,进行训练。
使用教程:
大致步骤
在工程下新建一个文件夹VOC2007,在下面就是新建几个默认名字的文件夹 Annotation,ImageSet(该目录还有三个文件需要建立),JPEGImages(把你所有的图片都复制到该目录里面,如下图),SegmentationClass,SegmentationObject。
--VOC2007 --Annotations --ImageSets --Main --Layout --Segmentation --JPEGImages --SegmentationClass --SegmentationObjectAnnotations 中主要存放xml文件,每一个xml对应一张图像, 并且每个xml中存放的是标记的各个目标的位置和类别信息,命名通常与对应的原始图像一样JPEGImages 自己的原始图像放在JPEGImages文件夹ImageSets Layout 存放人体部位的数据。(用不上) Main 存放的是目标识别的数据,主要有test.txt , train.txt, val.txt, trainval.txt四个文件。 Segmentation 存放分割的数据。(用不上)
有大神写了个程序,运行一下就直接建好了,如下:
def make_voc_dir(): os.makedirs('VOC2007/Annotations') os.makedirs('VOC2007/ImageSets') os.makedirs('VOC2007/ImageSets/Main') os.makedirs('VOC2007/ImageSets/Layout') os.makedirs('VOC2007/ImageSets/Segmentation') os.makedirs('VOC2007/JPEGImages') os.makedirs('VOC2007/SegmentationClass') os.makedirs('VOC2007/SegmentationObject')if __name__ == '__main__': make_voc_dir()
在VOC2007下新建一个test.py文件,复制如下代码
test.py文件:
import osimport random trainval_percent = 0.2train_percent = 0.8xmlfilepath = 'Annotations'txtsavepath = 'ImageSets\Main'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) ftrainval = open('ImageSets/Main/trainval.txt', 'w')ftest = open('ImageSets/Main/test.txt', 'w')ftrain = open('ImageSets/Main/train.txt', 'w')fval = open('ImageSets/Main/val.txt', 'w') for i in list: name = total_xml[i][:-4] + '\n' if i in trainval: ftrainval.write(name) if i in train: ftest.write(name) else: fval.write(name) else: ftrain.write(name) ftrainval.close()ftrain.close()fval.close()ftest.close()
运行test.py代码之后,生成如下文件,VOC2007数据集制作完成
生成的数据集不能供yolov3直接使用。需要运行voc_annotation.py ,classes以检测两个类为例(车和人腿),在voc_annotation.py需改你的数据集为。
voc_annotation.py文件
import xml.etree.ElementTree as ETfrom os import getcwd# 注意这里的‘2007’,也许你的就需要修改sets=[('2007', 'train'), ('2007', 'val'), ('2007', 'test')]# 注意类别classes = ['car','leg']def convert_annotation(year, image_id, list_file): # 注意路径 in_file = open('VOC%s/Annotations/%s.xml'%(year, image_id)) tree=ET.parse(in_file) root = tree.getroot() 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 cls_id = classes.index(cls) xmlbox = obj.find('bndbox') b = (int(xmlbox.find('xmin').text), int(xmlbox.find('ymin').text), int(xmlbox.find('xmax').text), int(xmlbox.find('ymax').text)) list_file.write(' ' + ','.join([str(a) for a in b]) + ',' + str(cls_id))wd = getcwd()for year, image_set in sets: # 注意路径 image_ids = open('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/VOC%s/JPEGImages/%s.jpg'%(wd, year, image_id)) convert_annotation(year, image_id, list_file) list_file.write('\n') list_file.close()
运行之后,生成如下三个文件:
如果出现这种解析xml文件出错的问题,就打开保存的文件,找到最下面,看看后面一张图片xml文件格式
打开yolo3.cfg文件。搜索yolo(共出现三次),每次按下图都要修改
参数修改说明:
coco,voc这两个文件都需要修改。
如果类别比较多,可以用下面程序生成voc_classes.txt
classes = ['SIGN_SPEED_5','SIGN_SPEED_20','SIGN_SPEED_30','SIGN_SPEED_40','SIGN_SPEED_50','SIGN_SPEED_60','SIGN_LOAD_LIMITED_30T','SIGN_LOAD_LIMITED_40T','SIGN_LOAD_LIMITED_55T','SIGN_HEIGHT_2_8M','RM_RIGHT','RM_island','RM_Motorway_lane','RM_Crosswalk_lane','RM_No_vehicle_lane','SIGN_Limit_LEFT','SIGN_Limit_Drive','SIGN_Limit_parking','SIGN_Limit_whistle','SIGN_STOP_TO_YIELD','SIGN_Attention_people','SIGN_Attention_child','SIGN_work_Ahead','SIGN_SLOW','SIGN_Limit_trucks','SIGN_Keep_right_road','SIGN_Stop_sign','SIGN_HEIGHT_2_3M']num2 = len(classes)# xml文件个数list_file = open('20200314.txt', 'w')#list_file.write(classes[0])for classe in classes: list_file.write(classe) list_file.write('\n')list_file.close()
因为程序中有logs/000/目录,你需要创建这样一个目录,这个目录的作用就是存放自己的数据集训练得到的模型。不然程序运行到最后会因为找不到该路径而发生错误。生成的模型trained_weights.h5如下
如下将self这三行修改为各自对应的路径
运行 python yolo_video.py --image,输入自己要检测的类的图片即可查看训练效果了。
Loss值:
四、识别
介绍代码框架,以及如何运行
全部工程源码:
训练数据集:
联系客服