【目标检测】【代码阅读】ubuntu16.04利用yolov3进行红绿灯检测

最近在做的一个事情,利用已有数据集训练yolov3来检测红绿灯,本文主要做一个记录当前遇到的一些问题及解决方法。
参考博主:maozezhong0
https://blog.csdn.net/maozezhong0/article/details/80144641
感谢!
电脑配置

  1. GPU:1660super
  2. 环境:Ubuntu16.04

首先yolov3系列训练数据集可以参考官网教程:yoloV3
下载好预训练的权重:权重
小白可以参考官网的教程好好跑一下yolov3的代码,一来熟悉一下代码,二来看看自己的电脑配置能不能跑这么大的数据集。

接下来需要制作自己的数据集

  1. 网络上找到数据集我大概找了一下有:Bosch数据集法国LARA数据集WPI数据集根据自己的情况下载数据集及label。
  2. 简单了解一下yoloV3需要的数据集格式:

–VOC
–Annotations
–ImageSets
–Main
–Layout
–Segmentation
–JPEGImages
–SegmentationClass//暂时可有可无
–SegmentationObject //暂时可有可无

其中JPEGImages存放你的数据集图片,格式设置为000001.jpg、000002.jpg,大部分数据集格式都不是这样,这就需要自己动手写代码改一下格式。
Annotation里放label,一般格式为xml文件。如果是自己制作数据集可以参考https://www.cnblogs.com/antflow/p/7350274.html。
3. 我首次在法国数据集LARA上跑了一下,对下载下来的图片和label我们需要处理成需要的格式,可以利用下面的python代码:


import os
import shutil
from os import getcwd

classes = ['Traffic_Light_go', 'Traffic_Light_stop', 'Traffic_Light_ambiguous', 'Traffic_Light_warning']

width = 640
hight = 480
size = [width,hight]

def process(file_path, out_path, image_in_path, image_out_path):
    #generate labels
    with open(file_path) as f:
        i = 0
        pic_indexs = []
        if os.path.exists(out_path):
            shutil.rmtree(out_path)
        os.mkdir(out_path)
        for line in f.readlines():
            strs = str.split(line)
            pic_index = strs[2]
            pic_indexs.append(pic_index)
            x1 = float(strs[3])
            y1 = float(strs[4])
            x2 = float(strs[5])
            y2 = float(strs[6])
            box = [x1, x2, y1, y2]
            x,y,w,h = convert(size, box)
            label = strs[-3][1:]+'_'+strs[-2][:-1]+'_'+strs[-1][1:-1]
            class_ = classes.index(label)
            with open(out_path+'/%s.txt'%(str(i).zfill(6)), 'w') as out:
                out.write('%s %s %s %s %s\n'%(class_, x, y, w, h))
            i = i+1
    
    #reorder pictures
    i = 0
    if os.path.exists(image_out_path):        
        shutil.rmtree(image_out_path)
    os.mkdir(image_out_path)
    for index in pic_indexs:
        pic_name = 'frame_'+index.zfill(6)+'.jpg'  #fill left null with zeros
        new_pic = str(i).zfill(6)+'.jpg'
        new_pic_path = image_out_path + '/' + new_pic
        old_pic_path = image_in_path + '/' + pic_name
        print(old_pic_path+' -> '+new_pic_path)
        shutil.copyfile(old_pic_path, new_pic_path)
        i = i+1
            

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)

wd = getcwd()
file_path = wd + '/label_old.txt' #这个路径是下载下来的label所存储动位置
out_path = wd +'/labels'
image_in_path = wd + '/Image_old' #这个路径是下载下来的图片存储动位置
image_out_path = wd + '/Images'
process(file_path, out_path, image_in_path, image_out_path)

在这里插入图片描述
整理成这个格式后运行一下上述preprocess代码即可。随后我们划分训练集和验证集。

python
import os
import shutil
import random
from os import getcwd

#return how many picturs in pics_path
def count(pics_path):
    count_ = 0
    for _, _, files in os.walk(pics_path):
        for file in files:
            count_ = count_+1
    return count_

#train validation genrate and split
def generate_train_validation(pics_path, train_path, validation_path, validation_size=0.2):

    if os.path.exists(train_path):
        os.remove(train_path)
    if os.path.exists(validation_path):
        os.remove(validation_path)

    count_ = count(pics_path)
    all_indexs = range(0, count_)
    test_nums = int(count_ * validation_size)
    validation_indexs = random.sample(all_indexs, test_nums)
    validation_indexs.sort()
    
    train_txt = open(train_path, 'w')
    validation_txt = open(validation_path, 'w')
    
    index = 0
    cur_count = 0
    for _, _, files in os.walk(pics_path):
        for file in files:
            if index<len(validation_indexs) and validation_indexs[index]==cur_count:
                validation_txt.write(pics_path+'/%s\n'%(str(cur_count).zfill(6)+'.jpg'))
                index = index + 1
                print(pics_path+'/%s\n'%(str(cur_count).zfill(6)+'.jpg -> test'))
            else:
                train_txt.write(pics_path+'/%s\n'%(str(cur_count).zfill(6)+'.jpg'))
                print(pics_path+'/%s\n'%(str(cur_count).zfill(6)+'.jpg -> train'))
            cur_count = cur_count+1
    
    train_txt.close()
    validation_txt.close()
    
    print('---------- split train and validation finished ----------')
    print('all pic nums = ' + str(count_))
    print('train pic nums = ' + str(count_-index))
    print('validation pic nums = ' + str(index))
    print('finish')

wd = getcwd()
pics_path = wd + '/JPEGImages'
train_path = wd + '/2018_train.txt'
validation_path = wd + '/2018_validation.txt'
generate_train_validation(pics_path, train_path, validation_path)
target_path = wd + '/ImageSets/Main'
if os.path.exists(target_path+'2018_train.txt'):
    os.remove(target_path+'/2018_train.txt')
if os.path.exists(target_path+'2018_validation.txt'):
    os.remove(target_path+'/2018_validation.txt')
os.system("mv " + train_path + ' ' + target_path+'/2018_train.txt')
os.system("mv " + validation_path + ' ' + target_path+'/2018_validation.txt''

4.修改一下配置文件:

  1. 修改cfg/voc.data文件,class为类别数目,改为4,train为训练数据txt所放的位置,valid为validation数据txt所放的位置,names为voc.names所放的位置,backup为模型训练过程中存储模型参数的位置,没有的话直接在darknet_master文件夹下创建一个,或者程序会自动给你创建一个。

  2. 修改/data/voc.name文件,一行一个“go”、“stop”、“warning”、“ambiguous”。

  3. 修改/cfg/yolov3-voc.cfg,用的哪个模型就修改哪个模型的.cfg文件,这边用动是yolov3-voc。1)修改batchsize=64和subdivisions=8,batch_size表示每一个批次用来训练的图片张数,subdivisions表示一个批分成几组导入训练。若出现GPU训练动时候提示memory_out可以修改这两个参数试试;2)filters=75->filters=27,计算公式为filters=3x(classes数目+5);3)[yolo]子参数下,classes大小改成你的训练数据的类别数目,这边为4,random改成0(关闭多尺度训练,如果显存足够可以置为1)

  4. 修改makefile文件。这里把gpu cudnn改成1.

  5. make一下,随后可以开始训练网络了。
    训练和测试:

./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg yolov3.weights

训练中的问题:
1.刚开始学习率为0是正常的,loss下降慢慢就会恢复正常
2.loss下降到0.3左右一般就不会下降了 可以停止学习。

我们可以看一下结果:
在这里插入图片描述
对于验证集还是能达到比较高的准确率 但是实际上运用在车上进行试验效果就比较差 容易出现漏检误检的现象
所以要是在国内实车上运行还是需要比较好的数据集。考虑后续自己动手做一下数据集来保证实车的准确性。

おすすめ

転載: blog.csdn.net/hgj1h/article/details/121366195
おすすめ