上一篇:
我给大家详细介绍了如何使用 YOLOv3 模型来训练自己的数据集。训练部分完成,本文将继续给大家详细介绍如何使用我们训练好的模型来进行图片的批量测试。
一、修改 detector.c 文件
1. 替换 void test_detector 函数
同样是在 darknet 目录下,打开 ./example 目录下的 detector.c 文件,找到 void test_detector 函数,将下面的代码替换原来的 void 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; char buff[256]; char *input = buff; float nms=.45; int i=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/xny/yolov3/darknet/predictions/out",0)==-1) //"/home/xny/yolov3/darknet/predictions"修改成自己的路径 { if (mkdir("/home/xny/yolov3/darknet/predictions/out",0777)) //"/home/xny/yolov3/darknet/predictions"修改成自己的路径 { printf("creat file bag failed!!!"); } } 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); printf("Try Very Hard:"); printf("%s: Predicted in %f seconds.\n", path, 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{ char b[2048]; sprintf(b,"/home/xny/yolov3/darknet/predictions/out/%s",GetFilename(path));//"/home/xny/yolov3/darknet/predictions"修改成自己的路径 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; } } } }
注意上面有三处需要修改的地方,分别是:
if(access("/home/xny/yolov3/darknet/predictions/out",0)==-1) //"/home/xny/yolov3/darknet/predictions"修改成自己的路径
if (mkdir("/home/xny/yolov3/darknet/predictions/out",0777)) //"/home/xny/yolov3/darknet/predictions"修改成自己的路径
sprintf(b,"/home/xny/yolov3/darknet/predictions/out/%s",GetFilename(path));//"/home/xny/yolov3/darknet/predictions"修改成自己的路径
务必将其中的 /home/xny/yolov3/darknet/predictions/ 修改为自己的路径,这个路径可以是任意的,主要是用来存放测试结果图片的。
2. 添加 GetFilename(char p)函数
还是打开 detector.c 文件,将下面这段代码全部复制添加在 detctor.c 文件的开头。
#include "darknet.h" #include <sys/stat.h> #include<stdio.h> #include<time.h> #include<sys/types.h> static int coco_ids[] = {1,2,3,4,5,6,7,8,9,10,11,13,14,15,16,17,18,19,20,21,22,23,24,25,27,28,31,32,33,34,35,36,37,38,39,40,41,42,43,44,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,67,70,72,73,74,75,76,77,78,79,80,81,82,84,85,86,87,88,89,90}; char *GetFilename(char *p) { static char name[20]={""}; char *q = strrchr(p,'/') + 1; strncpy(name,q,6); //注意后面的6,如果你的测试集的图片的名字字符(不包括后缀)是其他长度,请改为你需要的长度(官方的默认的长度是6) return name; }
注意有一处需要修改的地方:
strncpy(name,q,6); //注意后面的6,如果你的测试集的图片的名字字符(不包括后缀)是其他长度,请改为你需要的长度(官方的默认的长度是6)
其中,6 表示测试集图片的名字字符长度,需要根据你的实际情况进行修改。例如,图片名为“001.jpg”,则上面的 6 就应该改为 3。因此,为了测试方便,建议测试集所有图片的名字字符长度最好是一致的。
3. 重新编译
修改完 detector.c 之后,回到 darknet 目录下,重新使用 make 命令进行重编译。
$ make
二、创建测试集
其实测试集我们在训练 yolov3 模型的时候已经创建了。打开 darknet 目录下的 2007_test.txt 文件:
这里面这号存放的是当时我们划分的测试集图片的实际路径。注意,这里可以看到每张测试集图片名字字符长度是 17,故 strncpy(name,q,17) 这样。
三、批量测试
在 darknet 目录下,进入 backup 目录,查看你在训练的时候的到的最终模型的名字。
例如,最终得到的模型是“yolov3-voc_final.weights”。
在 darknet 目录下,输入下面的批量测试命令:
./darknet detect cfg/yolov3-voc.cfg backup/yolov3-voc_final.weights
当终端显示“Enter Image Path: ”时,输入“2007_test.txt”的绝对路径,例如:
$ Enter Image Path: /home/xny/yolov3/darknet/2007_test.txt
之后就开始进行批量测试了,生成的图片在 /home/xny/yolov3/darknet/predictions/out/ 目录下。
好了,关于 YOLOv3 详细的测试步骤就介绍到这里。上一篇的训练教程加上这一篇的测试教程基本能满足大家对自己的数据集进行训练和测试的需求了,赶快试一试吧~