虽然功能实现了,方法也很简单,但算不是最上层的方法。
已知:
进行批量测试的时候,使用./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
输出文本检测结果后,会在darknet/results
文件夹中生成comp4_det_test_类名.txt
(一个类别对应一个txt文件,有多少类别,就产生多少个txt文件)。
随便打开一个txt文件,里面的内容简单示例如下。每行都是一个目标。这样的话,看一下文件总共有多少行,就能得到这个类别对应的目标个数(直接打开每个类别的txt文件,鼠标点到最后一行,看一下右下角的行数)。
008681 0.999982 565.763733 1311.388672 633.671326 1377.522949
008683 0.999982 565.872070 1315.253906 635.104248 1377.797363
008690 0.999984 523.559265 1306.766113 585.476746 1366.243652
008692 0.999964 523.111206 1306.916748 586.848389 1367.439697
008705 0.999984 530.645020 1291.177368 596.593750 1356.693970
008724 0.999983 533.842834 1291.449829 603.227844 1355.802612
以下是darknet/example/detector.c
中的validate_detector
函数。如下第43行处的“comp4_det_test_
“是最终生成的文件的前缀名,是哪个种类,后面就会加上种类名。
void validate_detector(char *datacfg, char *cfgfile, char *weightfile, char *outfile)
{
int j;
list *options = read_data_cfg(datacfg);
char *valid_images = option_find_str(options, "valid", "data/test.list");
char *name_list = option_find_str(options, "names", "data/names.list");
char *prefix = option_find_str(options, "results", "results");
char **names = get_labels(name_list);
char *mapf = option_find_str(options, "map", 0);
int *map = 0;
if (mapf) map = read_map(mapf);
network *net = load_network(cfgfile, weightfile, 0);
set_batch_network(net, 1);
fprintf(stderr, "Learning Rate: %g, Momentum: %g, Decay: %g\n", net->learning_rate, net->momentum, net->decay);
srand(time(0));
list *plist = get_paths(valid_images);
char **paths = (char **)list_to_array(plist);
layer l = net->layers[net->n-1];
int classes = l.classes;
char buff[1024];
char *type = option_find_str(options, "eval", "voc");
FILE *fp = 0;
FILE **fps = 0;
int coco = 0;
int imagenet = 0;
if(0==strcmp(type, "coco")){
if(!outfile) outfile = "coco_results";
snprintf(buff, 1024, "%s/%s.json", prefix, outfile);
fp = fopen(buff, "w");
fprintf(fp, "[\n");
coco = 1;
} else if(0==strcmp(type, "imagenet")){
if(!outfile) outfile = "imagenet-detection";
snprintf(buff, 1024, "%s/%s.txt", prefix, outfile);
fp = fopen(buff, "w");
imagenet = 1;
classes = 200;
} else {
if(!outfile) outfile = "comp4_det_test_";
fps = calloc(classes, sizeof(FILE *));
for(j = 0; j < classes; ++j){
snprintf(buff, 1024, "%s/%s%s.txt", prefix, outfile, names[j]);
fps[j] = fopen(buff, "w");
}
}
int m = plist->size;
int i=0;
int t;
float thresh = .005;
float nms = .45;
int nthreads = 4;
image *val = calloc(nthreads, sizeof(image));
image *val_resized = calloc(nthreads, sizeof(image));
image *buf = calloc(nthreads, sizeof(image));
image *buf_resized = calloc(nthreads, sizeof(image));
pthread_t *thr = calloc(nthreads, sizeof(pthread_t));
load_args args = {0};
args.w = net->w;
args.h = net->h;
//args.type = IMAGE_DATA;
args.type = LETTERBOX_DATA;
for(t = 0; t < nthreads; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
double start = what_time_is_it_now();
for(i = nthreads; i < m+nthreads; i += nthreads){
fprintf(stderr, "%d\n", i);
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
pthread_join(thr[t], 0);
val[t] = buf[t];
val_resized[t] = buf_resized[t];
}
for(t = 0; t < nthreads && i+t < m; ++t){
args.path = paths[i+t];
args.im = &buf[t];
args.resized = &buf_resized[t];
thr[t] = load_data_in_thread(args);
}
for(t = 0; t < nthreads && i+t-nthreads < m; ++t){
char *path = paths[i+t-nthreads];
char *id = basecfg(path);
float *X = val_resized[t].data;
network_predict(net, X);
int w = val[t].w;
int h = val[t].h;
int nboxes = 0;
detection *dets = get_network_boxes(net, w, h, thresh, .5, map, 0, &nboxes);
if (nms) do_nms_sort(dets, nboxes, classes, nms);
if (coco){
print_cocos(fp, path, dets, nboxes, classes, w, h);
} else if (imagenet){
print_imagenet_detections(fp, i+t-nthreads+1, dets, nboxes, classes, w, h);
} else {
print_detector_detections(fps, id, dets, nboxes, classes, w, h);
}
free_detections(dets, nboxes);
free(id);
free_image(val[t]);
free_image(val_resized[t]);
}
}
for(j = 0; j < classes; ++j){
if(fps) fclose(fps[j]);
}
if(coco){
fseek(fp, -2, SEEK_CUR);
fprintf(fp, "\n]\n");
fclose(fp);
}
fprintf(stderr, "Total Detection Time: %f Seconds\n", what_time_is_it_now() - start);
}
将上述函数(darknet/example/detector.c
中的validate_detector
函数)中的comp4_det_test_
改成comp4_det_train_
,重新编译:
在darknet文件夹下打开一个终端窗口,输入:
make clean //清除已生成的编译文件
make -j8 //重新编译 -j8是为了加速
编译完成后,此时,(接下来这个过程不需要做)再次运行命令./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
,会在results文件夹下产生文件名为“comp4_det_train_+类别名称
“的文件。
以将darknet/scripts
中的2007_test.txt
重命名为2007_test原来的.txt
,将2007_train.txt
重命名为2007_test.txt
;
将darknet/scripts/VOCdevkit/VOC2007/ImageSets/Main
中的test.txt
重命名为test原来的.txt
,将train.txt
重命名为test.txt
。
完成这两步修改后,就可以运行命令:
./darknet detector valid cfg/voc.data cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
会在results文件夹下产生文件名为“comp4_det_train_+类别名称
“的文件。
挨个打开它们,统计行数即可~