文章目录
前言
在使用tensorflow-yolov3训练自己数据集的时候遇到了各种各样的问题,为方便下次复现并训练测试,本篇文章记录了从标注数据到测试结果一系列过程.
提示:以下是本篇文章正文内容,下面案例可供参考
一、标注数据集工具LabelImg使用
1.视频按帧进行保存图片
拿到数据视频或图片之后需要对其进行标注。如果是图片直接对其进行标注即可,如果是视频,需要按帧或跳帧进行保存图片,然后对其进行保存。
import os
import cv2
from tqdm import tqdm
'''
video_path:视频保存路径,所有视频保存到一个文件夹当中
feame_save_path:图片保存路径,我这里是按隔帧(15帧)进行保存的图片
上面两个路径调整完之后即可运行该程序,下面为其他说明:
T = 0:是保存图片的名字,如果使用yolov3训练,.png->.jpg
'''
video_path = "../Temp/videos/"
frame_save_path = "../Temp/frame_pictures/"
if not os.path.exists(video_path):
os.makedirs(video_path)
if not os.path.exists(frame_save_path):
os.makedirs(frame_save_path)
videos_path = os.listdir(video_path)
T= 0
for i in tqdm(range(len(videos_path))):
str = videos_path[i].split(".")[0]
temp_video_path = os.path.join(video_path, videos_path[i])
cap = cv2.VideoCapture(temp_video_path)
frame_count = int(cap.get(cv2.CAP_PROP_FRAME_COUNT))
for j in range(frame_count):
ret, frame = cap.read()
if j%15==0:
T= T+1
frame_save_path_temp = os.path.join(frame_save_path, f"{T}" + ".png")
print(str)
print(frame_save_path_temp)
cv2.imwrite(frame_save_path_temp, frame)
cap.release()
2.虚拟环境下下载和如何使用labellmg标注工具
1.进入到任何一个虚拟环境当中,使用下面命令进入,然后使用pip命令下载labelImg工具,操作如下:
2.使用labelImg命令进入到labelImg工具,以及labelImg工具说明:
进入labelImg工具命令:
进入之后会出现下面页面,找到左上角的View->Auto Save mode打开这是自动保存。然后按照下面图上红色字体操作:
创建文件夹,按照上面操作进行选择对应的文件夹:
3.绘制框并保存
3.labelImg中文版下载和使用
参考链接:https://blog.csdn.net/weixin_46034990/article/details/124588192
二、使用Tensorflow版本的yolov3进行训练
1.下载代码并配置对应的环境
代码下载链接:https://github.com/YunYang1994/tensorflow-yolov3.git
环境配置:
# 注意cudatoolkit下载使用conda命令进行下载,然后继续下载cudann。其他无顺序要求
tensorflow-gpu 1.11.0
cudatoolkit 9.0 1
cudnn 7.6.5 cuda9.0_0
pillow 5.3.0 pypi_0 pypi
numpy 1.15.1 pypi_0 pypi
scipy 1.1.0 pypi_0 pypi
wget 3.2 pypi_0 pypi
setuptools 39.1.0 pypi_0 pypi
2.按照格式转换生成yolov3所需要的格式txt文件
1.创建下图中红色框中文件目录
2.将使用labellmg标注好的图片和VOC格式的文件放置到下图对应位置
3.运行split.py文件,生成第一步的文件名文件
split.py文件代码如下所示,复制即可全是相对目录。
import os
import random
import sys
'''
This is split train val test trainval and get xml name
'''
root_path = '../VOC2007'
xmlfilepath = root_path + '/Annotations'
txtsavepath = root_path + '/ImageSets/Main'
if not os.path.exists(root_path):
print("cannot find such directory: " + root_path)
exit()
if not os.path.exists(txtsavepath):
os.makedirs(txtsavepath)
train_percent = 0.8
test_percent = 0.2
total_xml = os.listdir(xmlfilepath)
random.shuffle(total_xml)
num = len(total_xml)
list = range(num)
train = [data[:-4] for data in total_xml[:int(train_percent * num)]]
test = [data[:-4] for data in total_xml[int(train_percent * num):]]
ftrain = open(txtsavepath + '/train.txt', 'w')
ftest = open(txtsavepath + '/test.txt', 'w')
for data in train:
ftrain.write(data+'\n')
for data in test:
ftest.write(data+'\n')
ftrain.close()
ftest.close()
运行完代码之后会在下图中生成两个文件,里面每一行都是图片或xml的文件名:
4.然后运行scripts->voc_annotation.py文件,得到训练数据和测试数据文件
根据项目结构找到voc_annotation.py文件:
修改里面代码,使用下列代码进行替换:
import os
import argparse
import xml.etree.ElementTree as ET
def convert_voc_annotation(data_path, data_type, anno_path, use_difficult_bbox=True):
'''
替换成自己在labelImg中标注时候的分类名
'''
classes = ['light-close', 'light-white', 'light-red', 'light-yellow', 'light-green']
img_inds_file = os.path.join(data_path, 'ImageSets', 'Main', data_type + '.txt')
with open(img_inds_file, 'r') as f:
txt = f.readlines()
image_inds = [line.strip() for line in txt]
with open(anno_path, 'a') as f:
for image_ind in image_inds:
image_path = os.path.join(data_path, 'JPEGImages', image_ind + '.png')
annotation = image_path
label_path = os.path.join(data_path, 'Annotations', image_ind + '.xml')
root = ET.parse(label_path).getroot()
objects = root.findall('object')
for obj in objects:
difficult = obj.find('difficult').text.strip()
if (not use_difficult_bbox) and(int(difficult) == 1):
continue
bbox = obj.find('bndbox')
class_ind = classes.index(obj.find('name').text.lower().strip())
xmin = bbox.find('xmin').text.strip()
xmax = bbox.find('xmax').text.strip()
ymin = bbox.find('ymin').text.strip()
ymax = bbox.find('ymax').text.strip()
annotation += ' ' + ','.join([xmin, ymin, xmax, ymax, str(class_ind)])
print(annotation)
f.write(annotation + "\n")
return len(image_inds)
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument("--data_path", default="E:/recovery_source_code/tensorflow-yolov3-master/tensorflow-yolov3-master/my_data")
parser.add_argument("--train_annotation", default="../data/dataset/voc_train.txt")
parser.add_argument("--test_annotation", default="../data/dataset/voc_test.txt")
flags = parser.parse_args()
if os.path.exists(flags.train_annotation):os.remove(flags.train_annotation)
if os.path.exists(flags.test_annotation):os.remove(flags.test_annotation)
num1 = convert_voc_annotation('E:/recovery_source_code/tensorflow-yolov3-master/tensorflow-yolov3-master/my_data/VOCdevkit/VOC2007', 'train', flags.train_annotation, False)
num2 = convert_voc_annotation('E:/recovery_source_code/tensorflow-yolov3-master/tensorflow-yolov3-master/my_data/VOCdevkit/VOC2007', 'test', flags.test_annotation, False)
print('=> The number of image for train is: %d\tThe number of image for test is:%d' %(num1, num2))
注意训练完成之后会在data->dataset下面生成对应训练所需要的文件:
3.修改配置进行训练
修改data->classes文件中的类别名,跟scripts->voc_annotation.py当中的类别名保持顺序一致:
修改core->config.py当中的三个地方,如下所示:
# 更改为上面修改的类名地址
__C.YOLO.CLASSES = "./data/classes/voc.names"
# 更改为生成训练和测试的文件地址
__C.TRAIN.ANNOT_PATH = "./data/dataset/voc_train.txt"
__C.TEST.ANNOT_PATH = "./data/dataset/voc_test.txt"
最后运行train.py文件即可训练。
4.训练的时候出现Train loss和Test loss都为nan的情况如何解决
总结
本篇文章总结了从划分数据,标注数据一直到使用Tensorflow-yolov3版本进行训练自己的数据集。