yolov4 批量保存测试结果

项目场景:

用yolov4训练完,打算测试两千多张图片,并把检测结果保存到文件夹中。

问题描述:

之前参考了两篇博客的程序,测试以【0,1,2,3,......,n】(n<1000)格式编号的图片可以正常保存到文件夹中。

但此次图片的编号为【00001,0002,…,02000】这种格式,按之前的程序测试只能保存一张以000命名的图片,并且后面的图片会把前面的图像覆盖掉。


思考过程:

1. 考虑将图片名称重命名为整数格式,重命名程序是用Python写的

import os

class BatchRename():
    '''
    批量重命名文件夹中的图片文件
    '''
    def __init__(self):
        self.path = 'D:/output'   #表示需要命名处理的文件夹

    def rename(self):
        filelist = os.listdir(self.path) #获取文件路径
        total_num = len(filelist) #获取文件长度(个数)
        i = 1  #表示文件的命名是从1开始的
        for item in filelist:
            if item.endswith('.jpg'):  #初始的图片的格式为jpg格式的
                src = os.path.join(os.path.abspath(self.path), item)       
                dst = os.path.join(os.path.abspath(self.path), str(i) + '.jpg')
                try:
                    os.rename(src, dst)           
                    i = i + 1
                except:
                    continue
        print ('total %d to rename & converted %d jpgs' % (total_num, i))

if __name__ == '__main__':
    demo = BatchRename()
    demo.rename()

更简单的重命名方式——批处理命令,命名格式为0001,0002
将下面的rename.bat脚本文件放在要处理的文件夹,双击运行即可

@echo off
setlocal EnableDelayedExpansion
set /a n=10000
for /r %%i in (*.png)  do (

set /a n+=1
ren "%%i" "!n:~-4!.png"

)

2. 批量生成测试集文件名

import os
from os import listdir, getcwd
from os.path import join
if __name__=='__main__':
    source_folder='D:/github/darknet/build/darknet/x64/scripts/VOCdevkit/VOC2020/TESTImages/' #测试集所在位置
    dest = 'D:/github/darknet/build/darknet/x64/data/test.txt'  # test.txt文档要保存的位置
    file_list=os.listdir(source_folder)
    test_file= open(dest,'a') #追加写打开
    file_num=0
    for file_obj in file_list:
        file_path=os.path.join(source_folder,file_obj)
        file_name,file_extend=os.path.splitext(file_obj)
        file_num=file_num+1
        test_file.write(source_folder+file_name+'.jpg'+'\n')
test_file.close()

虽然这样能够成功生成保存测试结果,但最大值只能到999张,后面的又会覆盖掉前面的结果

解决方案:

还是修改源码吧,修改

detector.c

大不了重新编译一次,终于发现了之前GetFilename函数获取文件名的问题,只能复制文件名的前3个字符给保存的结果文件名,就导致之前出现一直会覆盖掉之前文件的错误
GetFilename函数用来得到输入的文件名

//char *GetFilename(char *p)
//{
//	static char name[20] = { "" };
//	char *q = strrchr(p, '/') + 1; //在文件名中从后往前查找第一个/
//	memset(name, ' ', sizeof(name)); //清除内存位置
//	strncpy(name, q, 10); // 把文件名复制到name中,最多复制n个字符
//	return name;
//}

char *GetFilename(char *p)
{
	static char name[20] = { "" };
	char *q = strrchr(p, '/') + 1; //在文件名中从后往前查找第一个/
	char *r = strchr(q, '.');
	int pos = q - r;
	memset(name, ' ', sizeof(name)); //清除内存位置
	// 去除文件后缀
	int i = 0;
	char *fn1 = 0;
	i = strlen(q);
	fn1 = q + i;
	while (fn1 > q)
	{
		if (*fn1 == '.')
		{
			*fn1 = 0;
			break;
		}
		fn1--;
	}
	//std::string filename = imgPath.substr(0, iPos);
	strncpy(name, q, 10); // 把文件名复制到name中,最多复制n个字符
	return name;
}

现在这样就好啦!
记得把下面这块也改一改,在1659行左右,
方法ctrl+F查找draw_detections_v3,修改上面那个

draw_detections_v3(im, dets, nboxes, thresh, names, alphabet, l.classes, ext_output);
//save_image(im, "predictions");
char b[1024];
sprintf(b, "output/%s", GetFilename(input));
save_image(im, b);

下面这一块是把每张图像的检测结果保存成一个txt文件,方便用于其他后处理过程。
这一段放在(draw_detections_v3(im, dets, nboxes, thresh, names, alphabet, l.classes, ext_output);)代码上方就可以。

		char t[2048];

		sprintf(t, "output/%s.txt", GetFilename(input));

		if (save_labels && nboxes > 0)
		{
			char labelpath[4096];
			//replace_image_to_label(input, labelpath);
			strcpy(labelpath, t);
			FILE* fw = fopen(labelpath, "wb");
			int i;
			for (i = 0; i < nboxes; ++i) {
				char buff[1024];
				int class_id = -1;
				float prob = 0;
				for (j = 0; j < l.classes; ++j) {
					if (dets[i].prob[j] > thresh && dets[i].prob[j] > prob) {
						prob = dets[i].prob[j];
						class_id = j;
					}
				}
				if (class_id >= 0) {
					//sprintf(buff, "%d %2.4f %2.4f %2.4f %2.4f\n", class_id, dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h);
					sprintf(buff, "%d %2.4f %2.4f %2.4f %2.4f %2.4f\n", class_id, dets[i].prob[class_id], dets[i].bbox.x, dets[i].bbox.y, dets[i].bbox.w, dets[i].bbox.h);

					fwrite(buff, sizeof(char), strlen(buff), fw);
				}
			}
			fclose(fw);
		}

最后重新编译一下就可以得到一个新的darknet.exe文件

测试前修改cfg文件,把#Testing 下的两行解除注释

[net]
# Testing
batch=1
subdivisions=1
# Training
batch=32
subdivisions=16
width=416
height=416
channels=3
momentum=0.949
decay=0.0005
angle=0
saturation = 1.5
exposure = 1.5
hue=.1

最后贴一下训练及测试的命令,谨此铭记

训练数据

darknet.exe detector train data/obj.data yolov-obj.cfg yolov4.conv.137

单张测试

darknet.exe detector test data/obj.data yolov-obj.cfg  backup/yolov-obj_800.weights test.jpg -i 0 -thresh 0.25 -gpus 0,1,2,3

批量测试结果保存至output文件夹

darknet.exe detector test data/obj.data yolov-obj.cfg  backup/yolov-obj_800.weights -ext_output < data/test.txt > result.txt -gpus 0,1,2,3

不想显示的话

darknet.exe detector test data/obj.data yolov-obj.cfg  backup/yolov-obj_800.weights -ext_output -dont_show < data/test.txt > result.txt -gpus 0,1,2,3

批量保存图像测试结果及标签文件,并不显示

darknet.exe detector test data/obj.data yolov-obj.cfg  backup/yolov-obj_800.weights -save_labels -ext_output -dont_show < data/test.txt > result.txt -gpus 0,1,2,3

想要输出坐标的话

darknet.exe detector test data/obj.data yolov-obj.cfg  backup/yolov-obj_800.weights -ext_output dog.jpg

你可能感兴趣的:(yolov4学习,python,深度学习,神经网络)