YOLOv2输出物体的位置坐标以及批次处理图片

大家在使用深度学习进行识别检测的时候,有时候不仅要将其找到判别种类,有时候我们还要对坐标进行分析。下面给大家讲述如何通过YOLOV2进行训练的时候是如何输出物体的位置坐标。

1.查看保存检测图片的源码

    大家阅读过源码肯定知道,在训练与检测的时候我们通常使用了YOLO里面的detector函数,而在不进行改变源码时,我们会将检测的图片存为darknet.exe同路径的“prediction.png”。由此我们可以查看保存检测图片的源码。

1.1首先在darknet/src/下找到image.c文件,找到(239行)的draw_detections函数,在规定位置将Boundingbox的坐标输出。

1.2保存Boundingbox坐标到一个.txt来做分析,这样我们可以实时的知道物体的类别以及位置。

    注意:在C语言中,打开文件并在里面写东西,使用'w+',即先清空该文件,在填写,使用'a+'的时候,即不清空文件,填写文件。

2.YOLO批次测试图片,并将检测好的图片放到特定文件夹

2.1选择图片

    选择测试图片,并将其放入文件夹下,使用如下图所示的python代码将测试图片的地址以及name存入.txt文档中,程序如下所示。并将该.txt的地址写入obj.data对应的valid里面。

from os import listdir,getcwd
import os
dir=getcwd()#得到该py文件的绝对路径
path=dir+'/Test'#写自己的地址即可(Test为自己文件夹的名称)
img_list=os.listdir(path)
img_file=open('test.txt','w')
for img in img_list:
	img_name,index=os.path.splitext(img)##将文件的名称以及后缀名分离
	img_file.write(path+'/'+img+"\n")
img_file.close()

2.2建立对应的.cfg

    为了方便大家可以建立不同的.cfg,如train.cfg以及test.cfg,这样我们在调试运行darknet的时候我们可以方便而且不会出错。(detector.c文件在darknet/examples,obj.data以及.cfg在darknet/cfg中)

2.3批次测试图片,并保存自定义文件夹

    实现了将文件放入某个特定的文件夹中(文件夹的名字及路径由自己设定),首先读取文件夹中图片的名称,并将图片的绝对路径保存在某一个txt文件中,在测试中,我们读取每个路径,对每个路径进行训练,并将测试好的图片放入特定文件夹中。

2.3.1更改后的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;
    bool flag_test=true;
    DIR *dir;
    char basePath[1000];
    memset(basePath,'\0',sizeof(basePath));
    strcpy(basePath,"/home/xinhan/darknet/scripts/Test_img");
    //basePath="/home/hx/darknet/test_img";
    readFileList(basePath);
    
    while(flag_test){
        if(filename)
	{
	    flag_test=false;
            strncpy(input, filename, 256);
        } 
	else 
	{
	    flag_test=false;
            //printf("Enter Image Path: ");
            fflush(stdout);
	    input="/home/xinhan/darknet/scripts/test_image.txt";
            //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/xinhan/darknet/scripts/out_image",0)==-1)//"/home/FENGsl/darknet/data"修改成自己的路径
            {
              if (mkdir("/home/xinhan/darknet/scripts/out_image",0777))//"/home/FENGsl/darknet/data"修改成自己的路径
               {
                 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/xinhan/darknet/scripts/out_image/%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("Test successfully!\n");	
}

2.3.2 GetFilename(char *p)函数

#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表示图片名称的长短,可根据自己图片名字来更改其数值
    return name;
}

2.3.3 readFileList函数

int readFileList(char *basePath)
{
    DIR *dir;
    struct dirent *ptr;
    char base[1000];
    FILE* ra =fopen("/home/xinhan/darknet/scripts/test_image.txt","w");
    if ((dir=opendir(basePath)) == NULL)
    {
        perror("Open dir error...");
        exit(1);
    }

    while ((ptr=readdir(dir)) != NULL)
    {
        if(strcmp(ptr->d_name,".")==0 || strcmp(ptr->d_name,"..")==0)    ///current dir OR parrent dir
            continue;
        else if(ptr->d_type == 8)    ///file
            {printf("d_name:%s/%s\n",basePath,ptr->d_name);
	    fprintf(ra,"%s/%s\n",basePath,ptr->d_name);}   
        else if(ptr->d_type == 10)    ///link file
            printf("d_name:%s/%s\n",basePath,ptr->d_name);
        else if(ptr->d_type == 4)    ///dir
        {
            memset(base,'\0',sizeof(base));
            strcpy(base,basePath);
            strcat(base,"/");
            strcat(base,ptr->d_name);
            readFileList(base);
        }
    }
    fclose(ra);
    closedir(dir);
    return 1;
}

 

2.3.4将函数添加进去后,重新make

2.3.5执行批次测试图片

./darknet detector test cfg/obj.data cfg/test.cfg [weights]

  默认输入的是我们既定好的路径。

2.4 YOLO指令

2.4.1测试并返回图片名称、类别以及置信度:./darknet detector train cfg/obj.data cfg/train.cfg [weights]

 然后在输入对应单张图片的绝对路径,即可判断出图片中存在物体的类别以及置信度。(原本的darknet带的未更改的test_detector函数)

2.4.2测试模型的好坏,得到其recall以及IOU:./darknet detector valid cfg/obj.data cfg/valid.cfg [weights]

2.4.2.1更改detector.c中的validate_detector_recall()函数,本次实验默认是obj.data中的valid

validate_detector_recall函数定义和调用改为:


void validate_detector_recall(char *datacfg, char *cfgfile, char *weightfile)

validate_detector_recall(datacfg, cfg, weights);

validate_detector_recall中的plist和paths如下所示(原本的)


list *plist = get_paths("data/voc.2007.test");

char **paths = (char **)list_to_array(plist);

更改为:


list *options = read_data_cfg(datacfg);

char *valid_images = option_find_str(options, "valid", "data/train.list");

list *plist = get_paths(valid_images);

char **paths = (char **)list_to_array(plist);

2.4.2.2更改完代码后从新编译,在输入命令即可得到下图所示的评判标准。

/*依次ID:图片序号从0开始,correct:累计检测正确的总框数,total:累计的总ground truth数,RPs/Img: 累计的总proposals/已检测图片数,IOU,Recall: correct / total,proposals:累计的总框数,Precision: correct / proposals*/

2.5 GPU/CPU训练模型

单GPU:./darknet -i <gpu_id>detector train cfg/obj.data cfg/train.cfg [weights]

多GPU:./darknet detector train cfg/obj.data cfg/train.cfg [weights] -gpus 0,1,2,3

CPU:./darknet -nogpu detector train cfg/obj.data cfg/train.cfg [weights] 

 

参考博客:https://blog.csdn.net/NNNNNNNNNNNNY/article/details/54561928

                https://blog.csdn.net/mieleizhi0522/article/details/79989754

  • 8
    点赞
  • 45
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值