前言
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;
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");
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;
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];
rgb[0] = red;
rgb[1] = green;
rgb[2] = blue;
box b = dets[i].bbox;
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;
fprintf(box_coordinate, "Class:%s, Box: %d %d %d %d\n", names[class], left, right, top, bot);
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);
}
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为脚本文件的名字。
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
name=${file%.*}
txtname=$name.txt
onlyname=${name##*/}
savename=$save_path$onlyname
./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
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)