YOLOv4(darknet版)后处理:显示置信度、保存检测框的内容到本地

08/15 12:46
阅读数 2.2K

之前写了一篇使用YOLOv4训练的博客:https://blog.csdn.net/Creama_/article/details/106209388。然后很多读者反映检测图片的结果中怎么没有置信度,怎么加?怎么改变检测框的粗细?框出来目标怎么保存到本地?等等。。。今天就先写一下这几部分的代码,希望作者AlexeyAB看到给我打钱。

显示置信度

打开src/image.c
查找"draw_detections_v3",找到这个函数的定义部分,注意是定义部分。拉到函数最后一部分,只要在对应位置加上三句:
char buff[20];
sprintf(buff, "(%2.0f%%)", selected_detections[i].det.prob[selected_detections[i].best_class] * 100);
strcat(labelstr, buff);
即可,然后保存,重新make。




    if (alphabet) {
        char labelstr[4096] = { 0 };
		char buff[20];	//加上这句
        strcat(labelstr, names[selected_detections[i].best_class]);
		sprintf(buff, "(%2.0f%%)", selected_detections[i].det.prob[selected_detections[i].best_class] * 100);  //加上这句
		strcat(labelstr, buff);	//加上这句
        int j;
        for (j = 0; j < classes; ++j) {
            if (selected_detections[i].det.prob[j] > thresh && j != selected_detections[i].best_class) {
                strcat(labelstr, ", ");
                strcat(labelstr, names[j]);
            }
        }
        image label = get_label_v3(alphabet, labelstr, (im.w*.01));
        draw_label(im, top + width, left, label, rgb);
        free_image(label);
    }

改变检测框的粗细

打开src/image.c
查找"draw_detections_v3",找到函数定义部分,在函数体里找到"draw_box_width",其中变量width就是检测框的粗细。作者是这样定义的:

int width = im.h * .002;
if (width < 1)
    width = 1;

变大变小怎么变,你来定。

保存检测框的内容到本地

1.修改detector.c

这一部分是在增加了批量检测图片的基础上,将所有检测框中的内容保存到本地。批量检测图片在之前的博客有写。
打开src/detector.c
查找"test_detector",找到这个函数的定义部分,再找到里面的draw_detections_v3, 如下图所示:
在这里插入图片描述


这里有一部分是之前批量保存图片的代码,为了在画框之前保存检测框的内容,把获取文件名的代码放到了draw_detections_v3前面,并且在其后加上保存检测框中目标的代码:

save_dets(im, dets, nboxes, thresh, b);

2.修改image.h和image.c

打开src/image.h
在文件末尾加上函数save_dets的声明:

void save_dets(image im, detection *dets, int num_boxes, float thresh, const char* name);

如下图所示:
在这里插入图片描述
保存后打开src/image.c
在文件开头加入函数save_dets的定义:


void save_dets(image im, detection *dets, int num_boxes, float thresh, const char* name){
    int reg[4];
    int width = im.w;
    int height = im.h;
    
    for(int i=0; i < num_boxes; ++i){
        int best_class = -1;
        float best_class_prob = thresh;
	    for (int j = 0; j < dets[i].classes; ++j){
	        if (dets[i].prob[j] > best_class_prob) {
	            best_class = j;
		        best_class_prob = dets[i].prob[j];
	        }
	    }
	    if (best_class >= 0){
	        box b = dets[i].bbox;
	        reg[0] = round((b.x - b.w / 2) * width);
            reg[1] = round((b.y - b.h / 2) * height);
            reg[2] = round(b.w * width);
            reg[3] = round(b.h * height);
            
            if (reg[0] < 0) reg[0] = 0;
            if (reg[0] > width - 1) reg[0] = width - 1;
            if (reg[1] < 0) reg[1] = 0;
            if (reg[1] > height - 1) reg[1] = height - 1;
            if (reg[2] + reg[0] > width) reg[2] = width - reg[0];
            if (reg[3] + reg[1] > height) reg[3] = height - reg[1];
	        
	        save_dets_cv(im, reg, name, i);
	    }
    }
}

如下图所示:
在这里插入图片描述

3.修改image_opencv.h和image_opencv.cpp

打开src/image_opencv.h
在文件末尾加上函数save_dets_cv的声明:

void save_dets_cv(image im, int reg[], const char* name, int i);

如下图所示:
在这里插入图片描述
保存后打开src/image_opencv.cpp
在文件末尾加上函数save_dets_cv的定义:


void save_dets_cv(image im, int reg[], const char* name, int i){
    cv::Mat mat = image_to_mat(im);
    cv::cvtColor(mat, mat, cv::COLOR_BGR2RGB);
    cv::Mat dets = mat(cv::Rect(reg[0], reg[1], reg[2], reg[3]));
    //string name_dets = name;
    char name_dets[256];
    sprintf(name_dets, "%s_dets%d.jpg", name, i);
    cv::imwrite(name_dets, dets);
}

如下图所示:
在这里插入图片描述
到这里代码就写完了,保存所有文件,重新make。输入检测的命令行,结果会保存在output/,如下图所示,带dets的是每个检测框中的内容,如果不想保存大图可以注释掉detector.c中的save_image。
在这里插入图片描述
因为C++学的不是很好,所以只能借助opencv的方法切片并保存,有更好的方法欢迎留言。



展开阅读全文
打赏
0
0 收藏
分享
加载中
更多评论
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部