转载来源:https://blog.csdn.net/qq_43211132/article/details/90640540
系统:ubuntu16.04.5 | 查看命令:cat /etc/issue |
---|---|
GPU:RTX 2070 | 查看命令:nvidia-smi |
python:2.7.15 | 查看命令:python |
opencv:3.4.0 | 查看命令:pkg-config --modversion opencv |
CUDA Version:8.0.61 | 查看命令:cat /usr/local/cuda/version.txt |
CUDNN:6.0.21 | 查看命令:cat /usr/local/cuda/include/cudnn.h |
训练过程
1.标注数据,用到的是原图和标注数据(XML)
可以用LabelImg工具标注。
链接:https://pan.baidu.com/s/11zsNoah9nIRDjqgPPQ-xxA 提取码:874q
2.下载yolov3项目工程
git clone https://github.com/pjreddie/darknet
cd darknet
make
- 1
- 2
- 3
3.修改Makefile文件
GPU=1
CUDNN=1
OPENCV=1
-gencode arch=compute_61,code=[sm_61,compute_61] 根据GPU版本修改
NVCC=/usr/local/cuda-8.0/bin/nvcc
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4.准备所需的数据集格式
1)建立VOCdevkit文件夹,里面为名为VOC2018的文件夹,在里面是4个文件夹,Annotations、 ImageSets、JPEGImages、labels
2)Annotations是存放标注的XML文件
ImageSets里面有个main文件夹,里面装着train.txt和val.txt,里面装的是图片名称的前缀儿
JPEGImages用于存放原图
labels用于存放每个图片目标数据的txt文件(纯数据)
3)执行getTxtOfTandV.py文件,提取文件名的前缀,并按1:9的比例分训练集和测试集(网上有)
#coding:utf-8
import os
import random
trainval_percent = 1 #训练验证数据集的百分比
train_percent = 0.9 #训练集的百分比
xmlfilepath = ‘/home/…/darknet/VOCdevkit/VOC2018/Annotations’ #xml文件的路径
txtsavepath = ‘/home/…/darknet/VOCdevkit/VOC2018/ImageSets/Main’ #txt文件的保存路径 # os.listdir() 方法用于返回指定的文件夹包含的文件或文件夹的名字的列表。这个列表以字母顺序。
total_xml = os.listdir(xmlfilepath)
num=len(total_xml) #列表的长度
list=range(num)
tv=int(numtrainval_percent) #训练验证集的图片个数
tr=int(tvtrain_percent) #训练集的图片个数 # sample(seq, n) 从序列seq中选择n个随机且独立的元素;
trainval= random.sample(list,tv)
train=random.sample(trainval,tr)
#创建文件trainval.txt,test.txt,train.txt,val.txt
ftrain = open(’/home/sys507/darknet/VOCdevkit/VOC2018/ImageSets/Main/train.txt’, ‘w’)
fval = open(’/home/sys507/darknet/VOCdevkit/VOC2018/ImageSets/Main/val.txt’, ‘w’)
for i in list:
name=total_xml[i][:-4]+’\n’
if i in train:
ftrain.write(name)
else:
fval.write(name)
#ftrainval.close()
ftrain.close()
fval.close()
#ftest .close()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
4)执行voc_label.py文件, 通过前缀来获取路径提取txt数据再生成两个名为train.txt和val.txt用于
存放图片路径的文件
带注解版:链接:https://pan.baidu.com/s/1hJ6bor2ZThFboZjQQODMzw 提取码:gd86
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[(‘2018’, ‘train’), (‘2018’, ‘val’)]
classes = [“foreignbody”]
def convert(size, box):
dw = 1./size[0]
dh = 1./size[1]
x = (box[0] + box[1])/2.0
y = (box[2] + box[3])/2.0
w = box[1] - box[0]
h = box[3] - box[2]
x = xdw
w = wdw
y = ydh
h = hdh
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(float(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()
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()
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
5.下载预训练权重
wget https://pjreddie.com/media/files/darknet53.conv.74
- 1
6.修改cfg/voc.data文件
classes= 1
train = /home/.../darknet/2018_train.txt
valid = /home/.../darknet/2018_val.txt
names = data/voc.names
backup = backup
- 1
- 2
- 3
- 4
- 5
7.修改data/voc.names文件
类别名
8.修改cfg/yolov3-voc.cfg文件
# Training
batch=64
subdivisions=16
filters=18
classes=1 3处
- 1
- 2
- 3
- 4
- 5
- 6
- 7
9.训练
./darknet detector train cfg/voc.data cfg/yolov3-voc.cfg darknet53.conv.74
- 1
10.批量测试
1)将.cfg文件修改为测试模式(注解去掉)
2)添加头文件:
#include <sys/stat.h>
#include<stdio.h>
#include<time.h>
#include<sys/types.h>
- 1
- 2
- 3
- 4
3)在开头加入
char *GetFilename(char *p)
{
static char name[20]={""};
char *q = strrchr(p,'/') + 1;
strncpy(name,q,6);//注意后面的6,如果你的测试集的图片的名字字符(不包括后缀)是其他长度,请改为你需要的长度(官方的默认的长度是6)
return name;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
4)将以下代码替换examples/detector.c中的test_detector函数,修改自己的路径
void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, char *outfile, int fullscreen) {
list *options = read_data_cfg(datacfg); char *name_list = option_find_str(options, "names", "data/names.list"); char **names = get_labels(name_list); image **alphabet = load_alphabet(); network *net = load_network(cfgfile, weightfile, 0); set_batch_network(net, 1); srand(2222222); double time; double start; double endTime ; double totalTime = 0.0; char buff[256]; char *input = buff; float nms=.45; int i=0; int number = 0; while(1){ if(filename){ strncpy(input, filename, 256); image im = load_image_color(input,0,0); image sized = letterbox_image(im, net->w, net->h); //image sized = resize_image(im, net->w, net->h); //image sized2 = resize_max(im, net->w); //image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h); //resize_network(net, sized.w, sized.h); layer l = net->layers[net->n-1]; float *X = sized.data; time=what_time_is_it_now(); network_predict(net, X); printf("%s: Predicted in %f seconds.\n", input, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); //printf("%d\n", nboxes); //if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms); if (nms) do_nms_sort(dets, nboxes, l.classes, nms); draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes); free_detections(dets, nboxes); if(outfile) { save_image(im, outfile); } else{ save_image(im, "predictions");
/*
#ifdef OPENCV
cvNamedWindow(“predictions”, CV_WINDOW_NORMAL);
if(fullscreen){
cvSetWindowProperty(“predictions”, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
}
show_image(im, “predictions”);
cvWaitKey(0);
cvDestroyAllWindows();
#endif*/
}
free_image(im);
free_image(sized);
if (filename) break;
}
else {
printf("Enter Image Path: ");
fflush(stdout);
input = fgets(input, 256, stdin);
if(!input) return;
strtok(input, “\n”);
list *plist = get_paths(input);
char **paths = (char **)list_to_array(plist);
printf("Start Testing!\n");
int m = plist->size;
if(access("/home/sys507/darknet2/data/out",0)==-1)//"/home/FENGsl/darknet/data"修改成自己的路径
{
if (mkdir("/home/sys507/darknet2/data/out",0777))//"/home/FENGsl/darknet/data"修改成自己的路径
{
printf("creat file bag failed!!!");
}
}
start=what_time_is_it_now();
for(i = 0; i < m; ++i){
char *path = paths[i];
image im = load_image_color(path,0,0);
image sized = letterbox_image(im, net->w, net->h);
//image sized = resize_image(im, net->w, net->h);
//image sized2 = resize_max(im, net->w);
//image sized = crop_image(sized2, -((net->w - sized2.w)/2), -((net->h - sized2.h)/2), net->w, net->h);
//resize_network(net, sized.w, sized.h);
layer l = net->layers[net->n-1];
float *X = sized.data;
time=what_time_is_it_now();
network_predict(net, X);
endTime = what_time_is_it_now()-time;
printf("Try Very Hard:");
printf("%s: Predicted in %f seconds.\n", path, endTime);
totalTime = totalTime + endTime;
number ++;
int nboxes = 0;
detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes);
//printf("%d\n", nboxes);
//if (nms) do_nms_obj(boxes, probs, l.w*l.h*l.n, l.classes, nms);
if (nms) do_nms_sort(dets, nboxes, l.classes, nms);
draw_detections(im, dets, nboxes, thresh, names, alphabet, l.classes);
free_detections(dets, nboxes);
if(outfile){
save_image(im, outfile);
}
else{
char b[2048];
sprintf(b,"/home/sys507/darknet2/data/out/%s",GetFilename(path));//"/home/FENGsl/darknet/data"修改成自己的路径
save_image(im, b);
printf("save %s successfully!\n",GetFilename(path));
/*
#ifdef OPENCV
cvNamedWindow(“predictions”, CV_WINDOW_NORMAL);
if(fullscreen){
cvSetWindowProperty(“predictions”, CV_WND_PROP_FULLSCREEN, CV_WINDOW_FULLSCREEN);
}
show_image(im, “predictions”);
cvWaitKey(0);
cvDestroyAllWindows();
#endif
*/
}
free_image(im);
free_image(sized);
if (filename) break;
}
printf("number: There are %d pictures.\n",number);
printf("time: it costs %f seconds.\n",totalTime);
printf("speed: Predicted %f in 1 seconds.\n",number/totalTime);
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
5)修改完要make编译
6)然后输入测试指令:
./darknet detector test cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
- 1
10.测试召回率
1)修改detector.c文件中validate_detector_recall函数
list *plist = get_paths("data/coco_val_5k.list");
换成
list *plist=get_paths("/home/.../darknet/2018_train.txt");
- 1
2)for(k = 0; k < l.w*l.h*l.n; ++k){
换成
for(k = 0; k < nboxes; ++k){
- 1
3)执行指令
./darknet detector recall cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
- 1