从Darknet官方下载代码,找到里面的Makefile
文件,用记事本打开。默认大家都有GPU、CUDA和CUDNN,将其中的GPU
、CUDNN
设置为1
。如果电脑安装了OPENCV,就将OPENCV
设置为1
。
如果你不确定你的电脑是否有OPENCV,就先设置成1
编译,如果编译报错,就把OPENCV
再改回0
就是了。直接在darknet文件夹内打开终端,输入make
开始编译。
(base) user@name: ~/darknet-master$: make
编译没有出错,并且daknet文件夹里面多了个darknet,命令行输入./darknet
,它有反应,并且回复你usage: ./darknet
,那么恭喜你,darknet环境配置好了。
(base) user@name: ~/darknet-master$: ./darknet
usage: ./darknet
在自己的数据集上训练模型,先给自己创个文件夹吧,命名my_project
行吧。然后把你所有的图片数据、标注文件放在这个my_project
文件夹里面。请把图片数据img和标注文件xml分开放,像下面这样
my_project
|———— xml
| |————picture0.xml
| |————picture1.xml
| ……
|———— img
|————picture0.jpg
|————picture1.jpg
……
图片数据img就是你想要训练的图片,标注文件xml就是通过labelimg画框后保存的.xml文件,一张图img一个标注xml文件,一一对应!
下一步,把这个process.py
脚本文件给我复制保存到my_project
文件夹里面!
import os
import random
train_percent = 0.85 # 按比例划分训练集
val_percent = 0.15 # 按比例划分验证集
xmlfilepath = './xml/'
txtsavepath = './img/'
total_xml = os.listdir(xmlfilepath)
num = len(total_xml)
list = range(num)
train = random.sample(list, int(num * train_percent))
val = random.sample(list, int(num * val_percent))
ftest = open('./test.txt', 'w') # 会生成一个test.txt文件用于当测试集
ftrain = open('./train.txt', 'w') # 会生成一个train.txt文件用于当训练集
fval = open('./val.txt', 'w') # 会生成一个val.txt文件用于当验证集
for i in list:
name = total_xml[i][:-4] + '\n'
if i in train:
ftrain.write(name)
else:
ftest.write(name)
if i in val:
fval.write(name)
ftrain.close()
fval.close()
ftest.close()
这个process.py
脚本运行一下,process.py
文件夹里会多3个文件,test.txt
、train.txt
、val.txt
,里面的内容只不过是把你的数据集分成三个类而已。
再下一步,把这个convert.py
脚本文件给我复制保存到my_project
文件夹里面!
import xml.etree.ElementTree as ET
import pickle
import os
from os import listdir, getcwd
from os.path import join
sets=[('my_project', 'train')]
sets2=[('my_project', 'test')]
classes = ["class1", "class2"] # 你的数据集类别
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('./xml/%s.xml'%(image_id))
out_file = open('./img/%s.txt'%(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')
for year, image_set in sets:
image_ids = open('./%s.txt'%(image_set)).read().strip().split()
list_file = open('./%s_%s.txt'%(year, image_set), 'w')
for image_id in image_ids:
list_file.write('./my_project/img/%s.jpg\n'%(image_id))
convert_annotation(year, image_id)
list_file.close()
for year2, image_set2 in sets2:
image_ids2 = open('./%s.txt'%(image_set2)).read().strip().split()
test_file = open('./%s_%s.txt'%(year2, image_set2), 'w')
for image_id2 in image_ids2:
test_file.write('./my_project/img/%s.jpg\n'%(image_id2))
convert_annotation(year2, image_id2)
test_file.close()
这个convert.py
文件运行后,会生成my_project_train.txt
、my_project_test.txt
。这个脚本的功能就是通过test.txt
、train.txt
、val.txt
的内容,整理训练图片路径,到时候训练的时候就需要用到这个my_project_train.txt
。
再下一步,你需要一个.names文件,也把他放在my_project
文件夹里,你可以命名为my_project.names
,里面的内容是你数据集的类别名:
再下一步,你需要创建一个weights
文件夹存放你训练保存的模型文件。你还需要一个.data文件,也把他放在my_project
文件夹里,你可以命名为my_project.data
,里面的内容是下面这样,最好请使用绝对路径:
到此为止,你的my_project
文件夹里面应该长这样:
my_project
|———— xml
| |————picture0.xml
| |————picture1.xml
| ……
|———— img
| |————picture0.jpg
| |————picture1.jpg
| ……
|———— weights
|———— process.py
|———— convert.py
|———— train.txt
|———— test.txt
|———— val.txt
|———— my_project_train.txt
|———— my_project_test.txt
|———— my_project.names
|———— my_project.data
接下来就到修改cfg文件啦!找到darknet-master/cfg
文件夹里面,这里面有非常多的cfg可以使用,选择一个你喜欢的模型,跟着我修改里面的数据!例如我选的yolov3-tiny.cfg
把里面Testing的注释掉,Training的取消注释
里面的一些参数到底是干什么的,表示什么,请去搜一搜别的CSDN博客吧~这里只介绍一下max_batches
是你训练迭代的epoch,step
的话有两个数组成,前一个数可以改为max_batches×0.8
,后一个数可以改为max_batches×0.9
。如果CUDA报错out of memory就把subdivisions
值调大,但是得是2的幂,一般8就行。
然后修改网络参数,找到[yolo]
把classes
和你的数据集对应,把上面的filters
改成(classes+5)×3
比如你是两个类的,那就classes=2
, filters=21
。
然后就是最后一步了!在命令行输入下面的代码开始训练!
(base) user@name: ~/darknet-master$: ./darknet detector train my_project/my_project.data cfg/yolov3-tiny.cfg -gpus 0
等着被训练数据刷屏就是了。模型最后会保存在weights
文件夹里面。
这是最简单的批量测试图片代码,直接将darknet-master/src/detecor.c
里面的test_detecot
函数全部替换成下面这样,再改个保存路径,重新make就好了!
void test_detector(char *datacfg, char *cfgfile, char *weightfile, char *filename, float thresh, float hier_thresh, int dont_show, int ext_output, int save_labels, char *outfile, int letter_box,int benchmark_layers)
{
list *options = read_data_cfg(datacfg);
char *name_list = option_find_str(options, "names", "data/names.list");
int names_size = 0;
char **names = get_labels_custom(name_list, &names_size); //get_labels(name_list);
image **alphabet = load_alphabet();
network net = parse_network_cfg_custom(cfgfile, 1, 1); // set batch=1
if (weightfile) {
load_weights(&net, weightfile);
}
net.benchmark_layers = benchmark_layers;
fuse_conv_batchnorm(net);
calculate_binary_weights(net);
if (net.layers[net.n - 1].classes != names_size) {
printf(" Error: in the file %s number of names %d that isn't equal to classes=%d in the file %s \n",
name_list, names_size, net.layers[net.n - 1].classes, cfgfile);
if (net.layers[net.n - 1].classes > names_size) getchar();
}
srand(2222222);
double time;
char buff[256];
char *input = buff;
char *json_buf = NULL;
int json_image_id = 0;
FILE* json_file = NULL;
if (outfile) {
json_file = fopen(outfile, "wb");
char *tmp = "[\n";
fwrite(tmp, sizeof(char), strlen(tmp), json_file);
}
int j,i;
float nms = .45; // 0.4F
if (filename) {
strncpy(input, filename, 256);
list *plist = get_paths(input);
char **paths = (char **)list_to_array(plist);
printf("Start Testing!\n");
int m = plist->size;
for(i=0;i thresh && dets[i].prob[j] > prob) {
prob = dets[i].prob[j];
class_id = j;
}
}
if (class_id >= 0) {
sprintf(buff, "%d %2.4f %2.4f %2.4f %2.4f\n", class_id, dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h);
fwrite(buff, sizeof(char), strlen(buff), fw);
}
}
fclose(fw);
}
free_detections(dets, nboxes);
free_image(im);
free_image(sized);
}
}
printf("All Done!\n");
pause();
exit(0);
free_ptrs(names, net.layers[net.n - 1].classes);
free_list_contents_kvp(options);
free_list(options);
const int nsize = 8;
for (j = 0; j < nsize; ++j) {
for (i = 32; i < 127; ++i) {
free_image(alphabet[j][i]);
}
free(alphabet[j]);
}
free(alphabet);
free_network(net);
printf("All Done!\n");
pause();
}
记得重新make不然改了没用
(base) user@name: ~/darknet-master$: make
然后测试图片的指令是
(base) user@name: ~/darknet-master$: ./darknet detector test my_project/my_project.data cfg/yolov3-tiny.cfg my_project/weights/你的模型.weights my_project/my_project_test.txt