在师兄师姐的指导下的yolo学习,本博客上是记录用yolo训练自己的数据集(车牌),可能比较曲折,没有经验总是踩坑、、数据集是从网上下的图片自己标注的,数量很少,(导致了之后出现很多NAN)只想走个流程入个门。准备数据我是在windows系统下准备的,其余是linux系统下
- 准备数据
(1)从网页上下载图片
注:如果你想训练的是车牌,需要准备的是各种带有车牌的汽车的图片,而不是单纯的车牌。
# -*- coding: utf-8 -*-
# -*- coding:utf-8 -*-
import re
import uuid
import requests
import os
class DownloadImages:
def __init__(self, download_max, key_word):
self.download_sum = 0
self.download_max = download_max
self.key_word = key_word
#self.save_path = '../images/download/'
#self.save_path = 'E:/lixueqian/practice0/temp/'
self.save_path = 'E:/lixueqian/practice0/3/' #要保存的路径
def start_download(self):
self.download_sum = 0
gsm = 80
str_gsm = str(gsm)
pn = 0
if not os.path.exists(self.save_path):
os.makedirs(self.save_path)
while self.download_sum < self.download_max:
str_pn = str(self.download_sum)
#url为图片的链接
#url = 'http://image.baidu.com/search/flip?tn=baiduimage&ie=utf-8&'\
#'word=' + self.key_word + '&pn=' + str_pn + '&gsm=' + str_gsm + '&ct=&ic=0&lm=-1&width=0&height=0'
url = 'https://image.baidu.com/search/index?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1551426579141_R&pv=&ic=&nc=1&z=&hd=&latest=©right=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&word=%E6%B1%BD%E8%BD%A6%E5%9B%BE%E7%89%87+%E5%B8%A6%E8%BD%A6%E7%89%8C' \
'word=' + self.key_word + '&pn=' + str_pn + '&gsm=' + str_gsm + '&ct=&ic=0&lm=-1&width=0&height=0'
print(url)
result = requests.get(url)
self.downloadImages(result.text)
print ('下载完成')
def downloadImages(self, html):
img_urls = re.findall('"objURL":"(.*?)",', html, re.S)
print( '找到关键词:' + self.key_word + '的图片,现在开始下载图片...')
for img_url in img_urls:
print('正在下载第' + str(self.download_sum + 1) + '张图片,图片地址:' + str(img_url))
try:
pic = requests.get(img_url, timeout=50)
pic_name = self.save_path + '/' + str(uuid.uuid1()) + '.jpg'
with open(pic_name, 'wb') as f:
f.write(pic.content)
self.download_sum += 1
if self.download_sum >= self.download_max:
break
except Exception as e:
print('【错误】当前图片无法下载,%s' % e)
continue
if __name__ == '__main__':
downloadImages = DownloadImages(100, '车牌')
downloadImages.start_download()
(2)制作数据集标签生成xml文件
我的电脑上有( labelImg )标注软件,就用的这个软件。操作简单无过多技术含量。
用Open Dir(Ctrl + u) 打开图片所在文件夹
w 创建一个矩形框
d 下一张图片
a 上一张图片
Ctrl + r 更改默认注释目标目录(xml文件保存的地址)
Ctrl + s 保存
按照类别将图片中的目标进行矩形框标注,每标注一个目标后软件自动弹出类别信息以供选择。因为我的标注比较简单,所以不是很详细==需要请自行查找。
(3)将xml文件转成txt格式
可能会报出不能被0除的错误,说明你的图片没有成功读取,可以重新试一下,我还是不行就删掉了那个图片。
# -*- coding: utf-8 -*-
import os
import sys
import xml.etree.ElementTree as ET
import glob
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
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 xml_to_txt(indir,outdir):
os.chdir(indir) #改变当前工作目录到指定路径
annotations = os.listdir('.')
#annotations = glob.glob(str(annotations)+'*.xml')
for i, file in enumerate(annotations):
file_save = file.split('.')[0]+'.txt'
file_txt=os.path.join(outdir,file_save)
f_w = open(file_txt,'w')
# actual parsing
in_file = open(file)
tree=ET.parse(in_file)
root = tree.getroot()
for obj in root.iter('object'):
current = list()
name = obj.find('name').text
xmlbox = obj.find('bndbox')
xn = float(xmlbox.find('xmin').text)
xx = float(xmlbox.find('xmax').text)
yn = float(xmlbox.find('ymin').text)
yx = float(xmlbox.find('ymax').text)
size = root.find('size')
w = int(size.find('width').text)
h = int(size.find('height').text)
x, y, w, h = convert((w, h), [xn,xx,yn,yx])
#print xn
#f_w.write(xn+' '+yn+' '+xx+' '+yx+' ')
f_w.write('0')
f_w.write(' '+str(x) + ' ' + str(y) + ' ' + str(w) + ' ' +str(h)+ ' ')
#f_w.write(name.encode("utf-8")+'\n')
#f_w(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')
#f_w.write(name+ '\n')
#indir='/home/zgz/data-xml' #xml目录
#outdir='/home/zgz/data-txt' #txt目录
indir='E:/lixueqian/practice0/train_label' #xml目录
outdir='E:/lixueqian/practice0/train_txt' #txt目录
#indir='E:/lixueqian/practice0/pred_label' #xml目录
#outdir='E:/lixueqian/practice0/pred_txt' #txt目录
xml_to_txt(indir,outdir)
txt中的内容:类别(0) 中心点X(比例) 中心点Y(比例)box宽(比例)box高(比例)
现在就有了
我是在linux系统下训练的,出现了错误,因为应该把txt文件夹下的所有内容复制到图片(set)文件夹下的!
转战linux:
- 下载yolov3项目工程。
在命令行输入
git clone https://github.com/pjreddie/darknet
cd darknet
3.修改Makefile文件(文件就在下载的darknet文件夹内)
在命令行中输入gedit Makefile ;
我的设备是修改GPU=1 CODNN=1 OPENCV=1 ,保存退出;
在命令行make. 有了darknet图标,说明编译成功。
- 修改配置文件
在darknet/cfg/voc.data文件中进行如下修改:
classes= 1(由于我只训练车牌这一个类)
train =/home/tlx/darknet/mydata/trainImagePath.txt(训练图片的路径)
valid = /home/tlx/darknet/mydata/validateImagePath.txt(验证图片的路径)
names = data/plate.names
在做此操作之前:首先需要生成包含训练图片的路径和验证图片的路径的txt文件,然后新建.names文件(txt),里边是物体类别。
生成包含训练图片的路径和验证图片的路径的txt文件程序如下:
# -*- coding: utf-8 -*-
import os
#paths=['coco2014','Stanford','vehicleplate']
paths=['/media/xue/eac29254-8c2e-482c-922f-e6f630738393/workspace/yan1/darknet']
f=open('pred_all.txt', 'w')
for path in paths:
#p=os.path.abspath(path)+'/train_set'
p=os.path.abspath(path)+'/pred_set'
filenames=os.listdir(p)
for filename in filenames:
im_path=p+'/'+filename
print(im_path)
f.write(im_path+'\n')
f.close()
在cfg/yolo-voc.cfg文件中的[yolo]中的classes改为1(只有一个类),将[yolo]上面的一个卷积层的filters改为30,计算公式为filters=(classes+coord+1)*3,因此是(1+4+1)*3=18。(如果是yolov2则是filters=(classes+coord+1)*num)
注如果是训练的时候,需要注释掉testing中的batch和subdivisions,留下training中的。
- 下载预训练模型
yolov3下载darknet53.conv.74
https://pjreddie.com/media/files/darknet53.conv.74
注:如果是yolov2下载darknet19_448.conv.23:
http://pjreddie.com/media/files/darknet19_448.conv.23
将模型保存在放在darknet文件夹下,并在darknet文件夹路径下运行命令进行训练:
./darknet detector train cfg/voc.data cfg/yolo-voc.cfg cfg/darknet53.conv.74
(./darknet detector train 后边有三个相对路径参数:1(.data)2(voc.cfg)3(权重))
到着就开始出错。。。出现-nan