0. darknet介绍
1. 框架结构
2. 安装
2.1 下载
2.2 修改Makefile配置文件
2.3 编译
2.4 下载yolov3的预训练模型权重
2.5 测试是否安装成功
3. voc数据集训练,测试
3.1 准备voc数据集
3.2 将数据转换成darknet支持的格式
3.3 修改darknet/cfg下的voc.data,yolov3-voc.cfg和data/voc.names文件
3.4 下载darknet-53的预训练权重文件
3.5 开始训练
4. mAP测试
4.1 通过detector valid命令生成测试数据
4.2 使用darknet_voc_mAP测试mAP
4.3 分析compute_mAP.py文件内容
参考链接
Darknet是一个用C和CUDA编写的开源神经网络框架。它快速,易于安装,并支持CPU和GPU计算。
链接:https://github.com/pjreddie/darknet
git clone https://github.com/pjreddie/darknet
cd darknet
GPU=1 #如果使用GPU设置为1,CPU设置为0
CUDNN=1 #如果使用CUDNN设置为1,否则为0
OPENCV=0 #如果调用摄像头,还需要设置OPENCV为1,否则为0
OPENMP=0 #如果使用OPENMP设置为1,否则为0
DEBUG=0 #如果使用DEBUG设置为1,否则为0
# 指定nvcc路径
NVCC = /usr/local/cuda-9.0/bin/nvcc
make
可能存在的错误
./darknet: error while loading shared libraries: libcudart.so.10.0: cannot
解决方案:
sudo ldconfig /usr/local/cuda-9.0/lib64
mkdir weights # 将预训练权重保存到该目录下
wget https://pjreddie.com/media/files/yolov3.weights
./darknet detect cfg/yolov3.cfg yolov3.weights data/dog.jpg
其中参数含义如下:
1. 网络配置文件
2. 预训练模型权重
3. 测试图像
测试完成后会打印如下信息以及在根目录下生成一个prediciton.jpg文件为输出结果。
Loading weights from weights/yolov3.weights...Done!
data/dog.jpg: Predicted in 0.031283 seconds.
dog: 100%
truck: 92%
bicycle: 99%
数据集的结构如下,我把数据集Vocdevkit目录放到了scripts文件夹下
VOC2007
Annotaitons # 标记xml文件
ImageSets/Main # 训练,测试数据集txt文件
JPEGImages # 图像文件
yolov3提供了将voc数据集转为yolo训练所需要的格式脚本
python scripts/voc_label.py
经过上述脚本,在scripts文件夹下会生成几个txt文件,其中包含的是图像的路径
- 2007_test.txt # voc2007测试集
- 2007_train.txt # voc2007训练集
- 2007_val.txt # voc2007验证集
- 2012_train.txt # voc2012训练集
- 2012_val.txt # voc2012测试集
- train.txt # voc2007+voc2012的训练集
- train.all.txt # 所有样本集
如下是voc.data文件的内容,根据自己实际情况修改即可
classes= 20 # 类别总数
train = /home/xxx/darknet/scripts/train.txt # 训练集样本txt文件
valid = /home/xxx/darknet/scripts/2007_test.txt # 验证集样本txt文件
names = data/voc.names # 类别名称
backup = backup # 权重保存路径
yolov3-voc.cfg的文件默认不修改,如需修改请参考其他
voc.names文件中包含的是数据集的类别,对于voc数据集的类别如下,总共20类:
aeroplane
bicycle
bird
boat
bottle
bus
car
cat
chair
cow
diningtable
dog
horse
motorbike
person
pottedplant
sheep
sofa
train
tvmonitor
wget https://pjreddie.com/media/files/darknet53.conv.74
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74 -gups 0,1,2,3
mkdir results # 测试结果保存路径
./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights -out "" -gpu 0 -thresh .5
其中:-thresh为IOU阈值可以根据实际情况调节
通过上面命令在results文件夹下就可以得到不同类别的测试结果文件
darknet_voc_mAP是我自己写的一个用于测试基于darknet训练voc格式数据集mAP的项目。项目结构如下:
上述文件夹中重点是input文件夹,里面包含了如下一些文件夹:
- detection-results # 来源4.1的测试数据
- ground-truth # voc的测试集xml文件
- images-optional # 如果gt的bounding box的坐标存在归一化需要测试集的images
- test.txt # 测试集的文件序号
使用方法,即将4.1得到的预测数据放到detection-results路径下,voc的测试集的xml文件放到ground-truth文件夹下,将数据集中ImageSets/Main文件夹下的test.txt放到input文件夹下,然后运行如下命令,即可得到mAP.
python3 compute_mAP.py
输出结果大致如下:
aeroplane : 0.8878980127914309
bicycle : 0.8618205446114344
bird : 0.7480539480998687
boat : 0.7048997455770187
bottle : 0.6794095545317449
bus : 0.8635922538078116
car : 0.8899740616851775
cat : 0.8743744101970683
chair : 0.5987828351364424
cow : 0.866211540175532
diningtable : 0.7244442845069334
dog : 0.8581894889390733
horse : 0.8902089938157063
motorbike : 0.8571526878469593
person : 0.8404120889508571
pottedplant : 0.5042149724691987
sheep : 0.8150808201092643
sofa : 0.7711258567989381
train : 0.8566713335712046
tvmonitor : 0.7672438110465113
***************************
mAP : 0.7929880622334087
该代码里面提供了两个额外的功能:
# 针对coco数据集训练测试mAP
# 1. coco数据集提供的gt数据中bounding box是经过归一化的所以需要反归一化,这里需要测试集的images数据 # scripts/coco2voc.py
# 2. 就是生成xml格式的文件 # scripts/xml_maker.py# 在detector valid生成测试数据时,没有指定-out参数会生成comp4_det_类别.txt的文件所以需要重命名一下测试数据
from voc_eval import voc_eval
import os
# 获取当前文件的路径
current_path = os.getcwd()
# 下面这块代码主要是针对coco数据集训练测试mAP
# 1. coco数据集提供的gt数据中bounding box是经过归一化的所以需要反归一化,这里需要测试集的images数据
# 2. 就是生成xml格式的文件
# --------------- 处理coco格式的ground-truth文件 ------------------
# 0. ground-truth的绝对路径
gt_path = os.path.join(current_path, "input", "ground-truth")
# image文件夹绝对路径
images_path = os.path.join(current_path, "input", "images-optional")
# 1. 判断文件格式
gt_files = os.listdir(gt_path)
if gt_files[0].endswith("txt"):
print("the ground truth is in coco format, need to convert to voc format!\n")
# coco转voc需要保证image文件存在
try:
# 2. 将coco格式的gt转换成voc格式
from scripts.coco2voc import convert2voc
import shutil
gt_coco = os.path.join(current_path, "input", "ground-truth-coco")
gt_voc = os.path.join(current_path, "input", "ground-truth-voc")
# 新建文件夹
os.mkdir(gt_coco)
os.mkdir(gt_voc)
for file in gt_files:
# 将coco的数据移动coco的文件夹中
shutil.move(os.path.join(gt_path, file), os.path.join(gt_coco, file))
prefix_fileName = file.split(".")[0]
img_path = os.path.join(images_path, prefix_fileName+".jpg")
coco_path = os.path.join(gt_coco, file)
voc_path = os.path.join(gt_voc, prefix_fileName+".txt")
# convert
convert2voc(img_path=img_path, txt_path=coco_path, out_path=voc_path)
except Exception:
print("please confirm image file !!\n")
# 3. 将voc格式的gt转换成xml的表现形式
from scripts.xml_maker import maker
maker(img_dir=images_path, label_dir=gt_voc, out_dir=gt_path)
# ----------------------------------------------------------------------
# 生成测试集文件
test_path = os.path.join(current_path, "input", "test.txt")
with open(test_path, "w", encoding="utf-8") as f:
for file in os.listdir(gt_path):
raw = file.strip().split(".")[0]
f.write(raw + "\n")
# -----------------------------------------------------------------
# 预测结果绝对路径
results_path = os.path.join(current_path, "input", "detection-results")
sub_files = os.listdir(results_path)
# ------------------- 处理darknet的预测文件 ----------------
# 判断是否存在字符“_”从而修改文件的命名
for idx, fileName in enumerate(sub_files):
if "_" in fileName:
print("change the ground-truth filename ...")
replaceName = fileName.strip().split("_")[-1]
# 重命名
sub_files[idx] = replaceName
os.rename(os.path.join(results_path, fileName), os.path.join(results_path, replaceName))
# ---------------------------------------------------------
# --------------------- mAP测试 -------------------------
mAP = []
for i in range(len(sub_files)):
class_name = sub_files[i].split(".txt")[0]
rec, prec, ap = voc_eval('./input/detection-results/{}.txt',
'./input/ground-truth/{}.xml',
'./input/test.txt',
class_name,
'./input/cache')
print("{} :\t {} ".format(class_name, ap))
mAP.append(ap)
mAP = tuple(mAP)
print("***************************")
print("mAP :\t {}".format(float(sum(mAP) / len(mAP))))
# ----------------------------------------------------------------
项目分享链接:链接:https://pan.baidu.com/s/1PcaPBwQz3cpLQs2I7EYEYQ
提取码:8ych
请记得解压input文件夹下的ground-truth压缩包,因为百度云上传有文件个数限制!!!
YOLOv3 mAP计算教程
darknet整体框架