因为项目中的需要,本篇博文实现输出(保存)yolo的测试结果,并测试结果的坐标位置切割原图,并不需要知道每个框的类别,保存了top9。
主要对src/image.c文件中的draw_detections函数做了修改。
//添加了 char *filename ,为了得到当前的图片名。
void draw_detections(image im, int num, float thresh, box *boxes, float **probs, float **masks, char **names, image **alphabet, int classes, char *filename)
{
printf("num %d\n", num);
float rawmax[num];
int i,j;
int params[3];
char savePath[100] = "";
//为了得到top19的框,将每个框按照最大概率值进行了排序,取了top19. b,c矩阵都是为了得到top9对应的原框的下标,好得到坐标点。
for(i =0; i0];
for(j =0;jif(probs[i][j] > rawmax[i]){
rawmax[i] = probs[i][j]; }
}
}
for( i =0;iif(rawmax[i] > 0)
printf("rawmax[ %d]:%f\n",i,rawmax[i]);
}
float b[num];
int c[num];
for(i =0; i1+ i++){
b[i] = rawmax[i];
}
int x;
for(i =0;ifor(x = i,j = x+1; jif(b[x]x = j;
if(x!=j){
j= b[i];
b[i] = b[x];
b[x] = j;
j = c[i];
c[i] = c[x];
c[x] = j;
}
}
//输出top9的坐标,后面的代码注释掉了,因为我只需要根据坐标切割出子图并保存。
for( i =0;i<9;i++){
box b = boxes[c[i]];
int left = (b.x-b.w/2.)*im.w;
int right = (b.x+b.w/2.)*im.w;
int top = (b.y-b.h/2.)*im.h;
int bot = (b.y+b.h/2.)*im.h;
if(left < 0) left = 0;
if(right > im.w-1) right = im.w-1;
if(top < 0) top = 0;
if(bot > im.h-1) bot = im.h-1;
printf("c[%d]=%d %d %d %d %d\n", i,c[i],left,right,top,bot);
//接下来的操作需要导入opencv,在文件头应该加入
#ifdef OPENCV
#include "opencv2/highgui/highgui_c.h"
#include "opencv2/imgproc/imgproc_c.h"
#endif
CvRect box = cvRect(left, top, right-left, bot-top);
IplImage* src = cvLoadImage(filename, -1);
CvSize size = cvSize(right-left, bot-top);
IplImage* roi = cvCreateImage(size, src->depth,src->nChannels);
cvSetImageROI(src, box);
cvCopy(src,roi,NULL);
char name1[4] = "dog";
char name2[5] = ".jpg";
char newname[100];
sprintf(newname,"%s_%d%s",name1,i,name2 ); //保存的图片名dog_i.jpg
cvSaveImage(newname,roi,0);
cvReleaseImage(&src);
cvReleaseImage(&roi);
}
因为这里讲行数参数加入了 char * filename,所以应该在对应的头文件中修改函数定义。
include/darknet.h ,修改函数定义为:
void draw_detections(image im, int num, float thresh, box *boxes, float **probs, float **masks, char **names, image **alphabet, int classes, char* filename);
examples/detector.c 的函数调用改为:
draw_detections(im, l.w*l.h*l.n, thresh, boxes, probs, masks, names, alphabet, l.classes, filename);
还有一些别的地方,因为加入了这个参数需要改动,根据make的提示,修改即可。
如果需要检测批量图片,只需要修改examples/detector.c 中的test_detector()函数
//加入filelist.读取test.txt,test.txt中每行保存一个图片路径
char **filelist = get_labels("../test.txt");
将:
while(1){
if(filename){……
……
}
改为:
int index = 0;
while(filelist[index] != NULL){
filename = filelist[index];
printf("filename: %s\n", filename);
if(filename){ ……
……
index++;
}
去掉:
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
}
以及 if (filename) break;
修改后的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;
int j;
float nms=.3;
char **filelist = get_labels("/home/wc/YOLO/darknet/data/test.txt");
int index = 0;
while(filelist[index] != NULL){
filename = filelist[index];
printf("filename: %s\n", filename);
// while(1){
if(filename){
strncpy(input, filename, 256);
} else {
printf("Enter Image Path: ");
fflush(stdout);
input = fgets(input, 256, stdin);
if(!input) return;
strtok(input, "\n");
}
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];
box *boxes = calloc(l.w*l.h*l.n, sizeof(box));
float **probs = calloc(l.w*l.h*l.n, sizeof(float *));
for(j = 0; j < l.w*l.h*l.n; ++j) probs[j] = calloc(l.classes + 1, sizeof(float *));
float **masks = 0;
if (l.coords > 4){
masks = calloc(l.w*l.h*l.n, sizeof(float*));
for(j = 0; j < l.w*l.h*l.n; ++j) masks[j] = calloc(l.coords-4, sizeof(float *));
}
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);
//printf(boxes);
get_region_boxes(l, im.w, im.h, net->w, net->h, thresh, probs, boxes, masks, 0, 0, hier_thresh, 1);
if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, l.classes, nms);
//else if (nms) do_nms_sort(boxes, probs, l.w*l.h*l.n, l.classes, nms);
//printf("start draw_detection");
draw_detections(im, l.w*l.h*l.n, thresh, boxes, probs, masks, names, alphabet, l.classes, filename);
/*
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);
free(boxes);
free_ptrs((void **)probs, l.w*l.h*l.n);
// if (filename) break;
index++;
}
}
主要的修改就是这些了。满足了基本要求。