Mobilenet-SSD实现车辆检测 keras框架

准备工作

由于是课程大作业,因此对于精度等等啥的没有太大的要求,考虑到疫情原因,自己的电脑又垃圾,因此只好选择一个轻量级的网络来训练了(大模型电脑可能就炸了),再加上老师要求大家算法场景都不一样。。。总之,最后选择了MobileNet-SSD这个轻量级模型来实现车辆检测了。这篇博客就不介绍mobilenet-ssd的原理,关于其原理及网络结构在网上有许多资料,大家可以自行搜索学习。写这篇博客的主要目的是给自己做个笔记和总结,当然也希望能给一些同学一点帮助,下文如有什么不足之处,也希望大家指正批评。下面进入正题。

源码下载

首先是源码下载,考虑到电脑环境:Win10+keras2.2+tensorflow-gpu1.11,因此选择了一个keras框架的mobilnet-ssd实现:
链接: github.
选择该代码的原因在于该代码功能相对简单,并未有太多目标检测的tricks,代码更容易看懂。当然还有个最重要的原因是他是用中文写的readme。
下载完成后,找一个路径解压即可(最好别有中文字符的路径,避免不必要的麻烦)。

数据集下载

然后是数据集下载,车辆的开源数据集很多(如KITTI、UA-DETRAC等),我选择的是UA-DETRAC数据集,它是车辆检测和跟踪的数据集,在北京和天津的24个不同地方拍摄了近10个小时的视频,视频以每秒25帧(fps)的速度录制,分辨率为960*540像素。手动标注了8250个车辆,总共有121万个标记的边界框。数据集中的场景包含白天、黑夜、正面、侧面、雨天等场景。下载的地址:
链接: UA-DETRAC数据集下载.
非常感谢以上两位大佬的分享。

数据集处理

如果不是使用的UA-DETRAC数据集,可跳过这一步。
因为后期需要测试视频,而数据集测试集中给出的是图像,因此可以先把每个文件转化成视频(如果是用自己的视频测试,也可以不用进行这一步),转化代码如下:

#coding:utf-8

"""
description:由于测试时是希望使用视频,因此希望将图像转化成视频

author:     kuang
location:   D:\Video_homework\image_to_videos.py
time:        2020.4.17  by home
"""

import cv2 
import os

#图片路径
im_dir = 'Train/'
#输出视频路径
video_dir = 'train_video/'
#图片尺寸
img_size = (960,540)
#帧率
fps = 30

img_file = os.listdir(im_dir)
num_file = len(img_file)

print(img_file ,num_file)

#对图片文件进行遍历,从而对每一组文件创建每一个视频
for file in img_file:

    #获取图片数
    num_image = len(os.listdir(os.path.join(im_dir,file)))
    print(num_image)

    #fourcc = cv2.cv.CV_FOURCC('M','J','P','G')#opencv2.4
    fourcc = cv2.VideoWriter_fourcc(*'XVID') #opencv3.0

    videoWriter = cv2.VideoWriter(video_dir + file + ".avi", fourcc, fps, img_size)

    for i in range(1,num_image):
        im_name = os.path.join(im_dir + file, 'img' + str(i).zfill(5) +'.jpg')
        print(im_name)
        frame = cv2.imread(im_name)
        cv2.imshow("data" , frame)
        cv2.waitKey(1)
        videoWriter.write(frame)
        #print(im_name)

    videoWriter.release()
    print("%s finish" % file)

然后根据下载的数据集中的文件看出,其标注文件是两种:一种是视频类型的xml文件,一种是给出了gt的txt,txt中的参数形式是xmin,ymin,xmax,ymax。而源码需要将标注形式转化为voc格式,因此,可以先将gt的txt转化为对应的每一张图片的xml,然后再按照源码操作就可以了。(当然,也可以直接转化为训练使用的txt,此处是考虑到要和后面的github上的步骤一一对应因此选择转化成xml)。
转化代码如下,有两个文件,先运行第一个文件(将gt中的浮点型坐标转化为整形,这个代码就可以实现直接转化为可以训练的txt文件了):

#coding:utf-8

"""
description:将train_gt.txt转化为voc格式的txt文件

author:     kuang
location:   D:\Video_homework\txt_to_traintxt.py
time:       2020.4.18  by home
"""

import os

#读取txt的内容
with open("train_gt.txt" , "r") as f:
    data = f.readlines()

with open("train.txt" , "w" ,encoding="utf-8") as fw:
    #对每一行进行处理
    for inf in data:

        #分割每一行的数据
        temp_data = inf.splitlines()[0].split(" ")
        print(temp_data)

        #提取图片名
        img = temp_data[0]

        #提取坐标信息,每4个1组(并且已经是xmin ymin xmax ymax),需要转化成整形同时变为xmin,ymin,xmax,ymax,class这种形式
        axis = temp_data[1:]

        temp = []
        for i in range(0,len(axis),4):
            location = axis[i:i+4]

            #将列表中的每一项转化为整形
            for a in range(4):
                location[a] = str(int(float(location[a])))

            #将4个列表转化为一个字符串并填充如,   同时每组加上对应的类别号(由于都是某一类别所以全部弄成0就可以了(也可以改为其他的))
            string = ",".join(location) + "," + "0"
            temp.append(string)

        #将一整行的axis全部弄成一组
        line_string = " ".join(temp)

        #最后写入的某一整行数据
        write_inf = img + " " + line_string

        #写入txt
        fw.write(write_inf)
        fw.write("\n")

如果想再转化为xml文件,则再运行下面的代码:

#coding:utf-8

"""
description:将train_gt.txt转化为voc格式的txt文件

错误:train_gt(82085)与图片数(83800)不对应,从文件夹MVI_39761开始
author:	网上copy修改的
location:   D:\Video_homework\txt_to_xml.py
time:       2020.4.18   by home
"""

import os, sys
import glob
from PIL import Image


#图像存储位置
src_img_dir = "Train/"
#图像的 ground truth 的 txt 文件存放位置
src_txt_dir = "train.txt"
src_xml_dir = "Annotations/"

#图像大小
img_size = (960,540)

# open the crospronding txt file
gt = open(src_txt_dir).read().splitlines()

a = 1
for inf in gt:

    #提取dir
    tempp = inf.split(" ")
    label = tempp[1:]
    dir_name,img_names = tempp[0].split("/")

    img = img_names.split(".")[0]
    if not os.path.exists(src_xml_dir + dir_name):     #判断当前路径是否存在,没有则创建new文件夹
        os.makedirs(src_xml_dir + dir_name)

    #img_Lists = glob.glob(src_img_dir + file + '/*.jpg')


    #获取img的width和height
    width, height = img_size

    # write in xml file
    # if not os.path.exists(src_xml_dir + file + "/" + img + ".xml" ):     #判断当前路径是否存在,没有则创建new文件夹
    #     open(src_xml_dir + file + "/" + img + ".xml" , "w" )
    #os.mknod(src_xml_dir + '/' + img + '.xml')
    xml_file = open((src_xml_dir + dir_name + '/' + img + '.xml'), 'w')
    xml_file.write('<annotation>\n')
    xml_file.write('    <folder>VOC2007</folder>\n')
    xml_file.write('    <filename>' + dir_name + "/" + img + '.jpg' + '</filename>\n')
    xml_file.write('    <size>\n')
    xml_file.write('        <width>' + str(width) + '</width>\n')
    xml_file.write('        <height>' + str(height) + '</height>\n')
    xml_file.write('        <depth>3</depth>\n')
    xml_file.write('    </size>\n')

    # write the region of image on xml file
    for img_each_label in label:
        spt = img_each_label.split(',') #这里如果txt里面是以逗号‘,’隔开的,那么就改为spt = img_each_label.split(',')。
        xml_file.write('    <object>\n')
        xml_file.write('        <name>' + str(spt[4]) + '</name>\n')
        xml_file.write('        <pose>Unspecified</pose>\n')
        xml_file.write('        <truncated>0</truncated>\n')
        xml_file.write('        <difficult>0</difficult>\n')
        xml_file.write('        <bndbox>\n')
        xml_file.write('            <xmin>' + str(spt[0]) + '</xmin>\n')
        xml_file.write('            <ymin>' + str(spt[1]) + '</ymin>\n')
        xml_file.write('            <xmax>' + str(spt[2]) + '</xmax>\n')
        xml_file.write('            <ymax>' + str(spt[3]) + '</ymax>\n')
        xml_file.write('        </bndbox>\n')
        xml_file.write('    </object>\n')

    xml_file.write('</annotation>')

    a += 1
    #循环添加,从而下一file读取gt时才会从对应位置读取
    print("完成%s的转化" % tempp[0])

print(a)

至此,转化完成,数据集就准备完成了,接下来就可以进行网络的训练了。

训练模型

第一步:下载Mobilenet-SSD的预训练权重mobilenet_ssd_weights,这个在源码中给出的百度云中下载。
第二步:将训练集的所有图片放在VOCdevkit文件夹下的VOC2007文件夹下的JPEGImages中,标签文件放在VOCdevkit文件夹下的VOC2007文件夹下的Annotation中。我的路径格式如图所示:
在这里插入图片描述
第三步:运行voc2ssd.py文件生成对应的txt(在ImageSets/main中会生成四个txt文件),但是运行前需根据自己的需求修改部分参数,在这个项目中可以把trainval_percent和train_percent都设置为1,因为这个项目在train.py中会随机划分训练和验证集,需要修改的地方如下图:
在这里插入图片描述
第四步:再运行根目录下的voc_annotation.py,运行前需要将classes改成你自己的classes。可参考修改成下图:
在这里插入图片描述
然后就会生成对应的2007_train.txt等三个文件,每一行对应其图片位置及其真实框的位置和类别。如下图(这里看出其实可以不用进行第二章的转化xml,而是直接将gt的txt转化成现在这个用于训练的txt):
在这里插入图片描述
第五步:在训练前需要修改model_data里面的voc_classes.txt文件,需要将classes改成你自己的classes。
第六步:然后将train.py文件中的部分参数修改,如batchsize、numclass以及预训练权重路径,如下图:
在这里插入图片描述
在这里插入图片描述
修改完成后,直接运行train.py即可开始训练。如图所示:
在这里插入图片描述
接下来就是漫长的等待了,当然如果电脑配置好还是非常快的。这个是我训练后的模型,效果还行,下载地址:
链接: 模型百度云下载.
提取码:avsl

测试

训练完成后即可开始测试模型了。

图片测试

修改根目录的ssd.py部分参数,主要是训练后的model和置信度,如图:
在这里插入图片描述
然后运行根目录的predict.py,即可进行图片的测试了,测试结果如图:
在这里插入图片描述
在这里插入图片描述

视频测试

操作同图片检测相同,只是还需要修改video.py中的测试视频地址,如图:
在这里插入图片描述
修改完成后,运行video.py,即可得到视频的测试结果了。

mAP评估

如果需要进行mAP的评估,则运行顺序如下:
1、首先,运行get_gt_txt.py,获取test集中的图片的ground_truth框,用于mAP计算
2、然后,运行get_dr_txt.py,用训练得到的模型对测试集进行测试,获取检测出的detection-results的txt
3、最后,运行get_map.py,即可获得mAP的计算结果了。

总结

最后,很感谢项目的作者以及数据集下载的博主的无私分享,也让我顺利的写完了整个大作业,下面是个人的一些总结:
1、正如最开始选择源码时所说的,这个项目的代码相对更简单,缺少很多目标检测的tricks,比方说多尺度训练等可以提升检测效果的方法,因此最后我测试的mAP也并没有太好。
2、这个项目是mobilenet-ssd,但是实际他的代码和mobilenet-ssd的网络结构还是有一定的出入的,比方说代码中每个尺度的priorbox数量是用的ssd的4、4、6、6、6、4,而不是mobilenet-ssd的3、6、6、6、6、6。
3、尽管代码还是有一定的错误,但是,个人觉得项目作者的代码还是很值得仔细的分析和学习的,有时间的同学可以考虑仔细研究一下代码。
以上是我个人的拙见,如果有不对的地方或是有什么问题,欢迎各位大佬留言指正批评,谢谢大家的阅读。

参考文献

感谢以下博文:
Mobilenet-SSD:轻量级目标检测模型在Keras当中的实现.
目标检测keras-ssd之训练自己数据.

  • 5
    点赞
  • 32
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值