Yolov1原理详细解读及实战(二)实战篇

Yolov1原理详细解读及实战(一)理论篇 中,我们对Yolov1网络结构、算法流程、训练及推理原理进行了详细剖析,本章进入实战环节,话不多说,马上开始!

环境

vscode+WSL:Ubuntu 18.04+python 3.9.7

Darknet安装

YOLOv1是Darknet深度学习框架进行训练和推理,首先安装Darknet。

步骤1:安装Darknet

git clone https://github.com/pjreddie/darknet
cd darknet
make -j8

在这里插入图片描述
步骤2:下载Yolov1预训练模型

wget http://pjreddie.com/media/files/yolov1.weights

步骤3:验证是否安装成功

./darknet yolo test cfg/yolov1.cfg yolov1.weights data/kite.jpg

在这里插入图片描述

运行结束后,在darknet目录下打开predictions.jpg即可查看结果。

在这里插入图片描述

模型训练

数据集准备

步骤1:下载VOC数据集。

wget https://pjreddie.com/media/files/VOCtrainval_06-Nov-2007.tar

解压后的文件结构如下:

└── VOCdevkit     #根目录
    └── VOC2007   #不同年份的数据集,这里只下载了2007
        ├── Annotations        #存放xml文件,与JPEGImages中的图片一一对应,解释图片的内容等等
        ├── ImageSets          #该目录下存放的都是txt文件,txt文件中每一行包含一个图片的名称,末尾会加上±1表示正负样本
        │   ├── Action
        │   ├── Layout
        │   ├── Main           #存放的是分类和检测的数据集分割文件
        │   │   ├── train.txt  #用于训练的图片名称
        │   │   ├── val.txt    #用于验证的图片名称
        │   │   ├── test.txt       #用于测试的图片名称
        │   │   ├── trainval.txt   #train与val的合集
        │   └── Segmentation
        ├── JPEGImages         #存放源图片
        ├── SegmentationClass  #存放的是图片,语义(class)分割相关
        └── SegmentationObject #存放的是图片,实例(object)分割相关

步骤2:将VOC2007格式数据转换为Yolo训练的格式。

Darknet需要的label不是xml格式,而是一张图片对应一个txt的形式,即每个标注框占一行。因此需要将xml格式转为txt格式。代码如下:

import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join

sets=[('2007', 'train'), ('2007', 'val')]

classes = ["bicycle", "boat", "dog", "cat","person"]


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)

def convert_annotation(year, image_id):
    in_file = open('VOCdevkit/VOC%s/Annotations/%s.xml'%(year, image_id))
    out_file = open('VOCdevkit/VOC%s/labels/%s.txt'%(year, image_id), 'w')
    tree=ET.parse(in_file)
    root = tree.getroot()
    size = root.find('size')
    w = int(size.find('width').text)
    h = int(size.find('height').text)

    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 = (float(xmlbox.find('xmin').text), float(xmlbox.find('xmax').text), float(xmlbox.find('ymin').text), float(xmlbox.find('ymax').text))
        bb = convert((w,h), b)
        out_file.write(str(cls_id) + " " + " ".join([str(a) for a in bb]) + '\n')

wd = getcwd()
print(wd)

for year, image_set in sets:
    if not os.path.exists('VOCdevkit/VOC%s/labels/'%(year)):
        os.makedirs('VOCdevkit/VOC%s/labels/'%(year))
    image_ids = open('VOCdevkit/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/VOCdevkit/VOC%s/JPEGImages/%s.jpg\n'%(wd, year, image_id))
        convert_annotation(year, image_id)
    list_file.close()

os.system("cat 2007_train.txt 2007_val.txt> train.txt")

运行结束之后,可以看到,生成了labels文件夹和2007_train.txt、2007_val.txt、train.txt。

在这里插入图片描述

labels文件夹中存放了每张图片的标注文件。例如:8 0.585 0.7306666666666667 0.122 0.3413333333333333 。含义如下:

<object-class> <x> <y> <width> <height>

其中,x,y,width和height是指标注框的左上角点坐标及宽高信息。

2007_train.txt、2007_val.txt表示训练集和验证集中图片的路径。代码最后执行 type 2007_train.txt 2007_val.txt > train.txt 将训练集和验证集放在了同一个txt中。

修改源代码并重新编译Darknet

步骤1:修改darknet/src/yolo.c

//改为自己的数据集类别
char *voc_names[] = {"bicycle", "boat", "dog", "cat","person"};
// train_images保存的是上述生成的train.txt
char *train_images = "VOCdevkit/VOC2007/train.txt";
//backup_directory是训练过程中生成的weights权重文件保存的路径
char *backup_directory = "darknet/backup/";

//修改数据集类别数为5(我的是5类)
draw_detections(im, l.side*l.side*l.n, thresh, boxes, probs, voc_names, alphabet, 5);
else if(0==strcmp(argv[2], "demo")) demo(cfg, weights, thresh, cam_index, filename, voc_names, 5, frame_skip, prefix);

步骤2:修改darknet/src/yolo_kernels.cu

# 修改数据集类别数为5(我的是5类)
draw_detections(det, l.side*l.side*l.n, demo_thresh, boxes, probs, voc_names, voc_labels, 5);

步骤3:修改darknet/cfg/yolov1/yolo.cfg

output= 735  //最后一层的全连接层,output=(5×2+classnum(=5))×7×7)
activation=linear

[detection]
classes= 5  //数据集类别

步骤4:重新编译Darknet。

cd darknet
make -j8

在这里插入图片描述

训练模型

步骤1:下载darknet.conv.weights。darknet.conv.weights是卷积网络在分类网络上预训练的权重,在此基础上训练。

wget http://pjreddie.com/media/files/darknet.conv.weights

步骤2:训练。

./darknet yolo train cfg/yolov1/yolo.cfg darknet.conv.weights

一切正常的话,就开始训练了。如图所示。

在这里插入图片描述

测试

./darknet yolo test cfg/yolov1/yolo.cfg backup/yolo_final.weights

然后输入一张图片,测试结果如下:

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穿着帆布鞋也能走猫步

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值