转载自:yolov3 批量处理图片获得检测框坐标_what_it_mean的博客-CSDN博客
HaLiXieDun 2021-02-24 13:59:03
799 正在上传…重新上传取消 收藏 10
分类专栏: yolov3 文章标签: 神经网络
版权
yolov3 专栏收录该内容
2 篇文章 0 订阅
订阅专栏
yolov3实现检测,需要所有检测框的坐标实现定位。
在darknet-master项目下实现检测框坐标的获取
系统:Windows
语言:C
项目:darknet-master
开发环境:VS 2019
脚本执行:Git
首先,我们要熟悉几个函数,这样可以更好地理解修改代码的原理
示例:
FILE* box_coordinate = fopen(output, "a+");
fprintf(box_coordinate, "Class:%s, Box: %d %d %d %d\n", names[class], left, right, top, bot);
fclose(box_coordinate);
解析:
FILE这个结构包含了文件操作的基本属性,对文件的操作都要通过这个结构的指针来进行,此种文件操作常用的函数见下表 函数 功能:
fopen() 打开流
fclose() 关闭流
fprintf() 按格式输出到流
1.fopen() fopen的原型是:FILE *fopen(const char *filename,const char *mode),fopen实现三个功能
为使用而打开一个流 把一个文件和此流相连接 给此流
返回一个FILR指针
参数filename指向要打开的文件名,mode表示打开状态的字符串。
2.fclose() fclose()的功能就是关闭用fopen()打开的文件,其原型是:int fclose(FILE *fp);如果成功,返回0,失败返回EOF。
3.fprintf() 按格式输入到流,其原型是int fprintf(FILE *stream, const char *format[, argument, …]);其用法和printf()相同,不过不是写到控制台,而是写到流罢了。
我们需要找到源码中画框的函数,这个函数中包含left, right, top, bot坐标信息,我们需要获取这些信息并写入到文本文件中。考虑到原函数有被多次调用,我们选择重构一个新的函数。进行画框的函数在darknet.sln里的image.c中,函数为draw_detections_v3。
我们真正需要修改的文件只有detector.c,image.c,image.h这三个文件。
重构函数加入到image.c文件中,这里主要参考了文章1
因为要获取所有检测框坐标,所以对代码进行了如下修改。可以放心复制粘贴。
void draw_detections_in_txt(image im, char* filename, detection* dets, int num, float thresh, char** names, image** alphabet, int classes)
{
int i, j;
char* output = filename;
//output = strcat(output, ".txt");
//output = strcat("./", output);
//printf("PATH:%s", output);
int namecount = 0;
for (namecount = strlen(filename) - 1; namecount >= 0; namecount--)
{
if ((filename[namecount] != 'j') && (filename[namecount] != 'p') && (filename[namecount] != 'g') && (filename[namecount] != '.'))
{
break;
}
else {
output[namecount] = '\0';
}
}
output = strcat(filename, ".txt");//将文件价里的.JPG文件名替换成.txt
FILE* box_coordinate = fopen(output, "w+"); //在循环前打开流
for (i = 0; i < num; ++i) {
char labelstr[4096] = { 0 };
int class = -1;
for (j = 0; j < classes; ++j) {
if (dets[i].prob[j] > thresh) {
if (class < 0) {
strcat(labelstr, names[j]);
class = j;
}
else {
strcat(labelstr, ", ");
strcat(labelstr, names[j]);
}
printf("%s: %.0f%%\n", names[j], dets[i].prob[j] * 100);
}
}
if (class >= 0) {
int width = im.h * .006;
/*
if(0){
width = pow(prob, 1./2.)*10+1;
alphabet = 0;
}
*/
//printf("%d %s: %.0f%%\n", i, names[class], prob*100);
int offset = class * 123457 % classes;
float red = get_color(2, offset, classes);
float green = get_color(1, offset, classes);
float blue = get_color(0, offset, classes);
float rgb[3];
//width = prob*20+2;
rgb[0] = red;
rgb[1] = green;
rgb[2] = blue;
box b = dets[i].bbox;
//printf("%f %f %f %f\n", b.x, b.y, b.w, b.h);
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;
///JiaXuejian asdded//
//printf("%d %d %d %d\n", left, right, top, bot);
///
//JiaXuejian added
//FILE* fp;
//if ((fp = fopen(output, "w+")) == NULL) {
// printf("wrong:\n");
//}
fprintf(box_coordinate, "Class:%s, Box: %d %d %d %d\n", names[class], left, right, top, bot);// 循环里将框坐标写入文件//"左部边框的位置:%d 顶部边框的位置:%d 右部边框的位置:%d 底部边框的位置:%d\n"
///
draw_box_width(im, left, top, right, bot, width, red, green, blue);
if (alphabet) {
image label = get_label(alphabet, labelstr, (im.h * .03));
draw_label(im, top + width, left, label, rgb);
free_image(label);
}
if (dets[i].mask) {
image mask = float_to_image(14, 14, 1, dets[i].mask);
image resized_mask = resize_image(mask, b.w * im.w, b.h * im.h);
image tmask = threshold_image(resized_mask, .5);
embed_image(tmask, im, left, top);
free_image(mask);
free_image(resized_mask);
free_image(tmask);
}
///JiaXuejian added//
// printf("%s:", label)
printf("%d %d %d %d\n", left, right, top, bot);
}
}
fclose(box_coordinate);//关闭流
}
由于是C代码,所以需要在头文件中声明一下新增的函数,darknet-master中大部分的函数声明在image.h 文件中,打开该文件,在34行可以看到 draw_detections 的函数声明,所以我们要输入以下代码:
void draw_detections_in_txt(image im, char* filename, detection* dets, int num, float thresh, char** names, image** alphabet, int classes);
我们需要找到引用draw_detections的地方,在detector.c中1690行,将其注释,增加新的重构函数的引用。
draw_detections_in_txt(im, input, dets, nboxes, thresh, names, alphabet, l.classes);
这里主要参考了文章2
在任意位置创建文本文件,另存为任意格式,文件名的后缀为.sh
打开git-bash
cd到脚本文件的路径下,执行以下命令
chmod +x script.sh
./script.sh
您可以将chmod更改为所需的可执行权限。
注意:chmod只需运行一次。如果要运行脚本,请运行./script.sh。script.sh为脚本文件的名字。
#在文件中写入
#! /bin/bash
sum=0
save_path="D:/darknet-master/build/darknet/x64/results_str/" #保存的地址
for file in D:/darknet-master/build/darknet/VOCdevkit2021/VOC2021/JPEGImages/*.jpg #图片所在的地址
do
if test -f $file
then
let sum += 1
#echo $file if file
name=${file%.*} #去掉.jpg的后缀
#echo $name
txtname=$name.txt #加上.txt的后缀
#echo $txtname
onlyname=${name##*/} #图片的名字a.jpg
#echo $onlyname
savename=$save_path$onlyname #图片保存的路径和名字
#echo $savename
./darknet detect -i 0 yolov3-voc.cfg results_mine/yolov3-voc_last.weights $file -out $savename #运行检测代码
mv $txtname $save_path
fi
echo sum=$sum
done
文章1
文章2
坐标是按照MFC:pic控件的矩形的left、right、top、bottom 坐标位置
left,top为左上角的点坐标
right,bottom为右下角的点坐标
转换一下为opencv常用的:
x=left
y=top
width=right-left
height=bottom-top
文章3