作为一名大四狗,在生产实习的时候老师叫我们做关于图像处理的课题,要求处理500张图片,还要求美观。AB大神的darknet识别出来的图像很美观,因此我用darknet做。但老师要求要提交500张图片的成果,我不可能一张一张去处理,但在网上搜索也没有很好的批处理教程,经过自己的努力,我做出来了,并将这个方法分享给大家,由于是第一次发博客,有什么不足的地方希望大家多批评。
windows环境下,需要用到VS
下载Darknet
如果有git的话 git clone https://github.com/AlexeyAB/darknet
没有的话打开 https://github.com/AlexeyAB/darknet 下载
下载yolov3
https://pjreddie.com/media/files/yolov3.weights
放到EXE同目录下,如图
因为要进行批量处理,所以要修改darknet的代码。
首先打开darknet_no_gpu.sln,如图
打开后修改detector.c
找到test_detector函数,对其进行修改
修改代码如下,其核心思想是增加一个for循环。建立一个文本文件,文本文件里面存放所需要处理照片的绝对路径。修改这个函数读取这个文件,用for循环一个一个获取文件绝对路径进行处理。直至结束。
注意下面代码有一处需要改的地方。即你新建一个文件夹,将目录放到代码里,生成的图片会保存在那,作者的文件夹是pictest2
double time;
char buff[256];
char *input = buff;
int j,i;
float nms = .45; // 0.4F
if (filename) {
strncpy(input, filename, 256);
list *plist = get_paths(input);
char **paths = (char **)list_to_array(plist);
printf("Start Testing!\n");
int m = plist->size;
for (i = 0; i < m; ++i) {
char *path = paths[i];
image im = load_image(path, 0, 0, net.c);
int letterbox = 0;
image sized = resize_image(im, net.w, net.h);
//image sized = letterbox_image(im, net.w, net.h); letterbox = 1;
layer l = net.layers[net.n - 1];
float *X = sized.data;
double time = get_time_point();
network_predict(net, X);
printf("%s: Predicted in %lf milli-seconds.\n", input, ((double)get_time_point() - time) / 1000);
printf("Try Very Hard:");
printf("%s: Predicted in %lf milli-seconds.\n", path, ((double)get_time_point() - time) / 1000);
int nboxes = 0;
detection *dets = get_network_boxes(&net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes, letterbox);
if (nms) do_nms_sort(dets, nboxes, l.classes, nms);
draw_detections_v3(im, dets, nboxes, thresh, names, alphabet, l.classes, ext_output);
char b[2048];
sprintf(b, "D:\\Ctext\\pictest2\\%d", i);这里换上自己的路径,即你希望生成图片所保存的位置
save_image(im, b);
printf("save %s successfully!\n", b);
if (save_labels)
{
char labelpath[4096];
replace_image_to_label(input, labelpath);
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);
fwrite(buff, sizeof(char), strlen(buff), fw);
}
}
fclose(fw);
}
free_detections(dets, nboxes);
free_image(im);
free_image(sized);
//free(boxes);
//free_ptrs((void **)probs, l.w*l.h*l.n);
}
}
printf("All Done!\n");
system("pause");
exit(0);
free_ptrs(names, net.layers[net.n - 1].classes);
free_list_contents_kvp(options);
free_list(options);
const int nsize = 8;
for (j = 0; j < nsize; ++j) {
for (i = 32; i < 127; ++i) {
free_image(alphabet[j][i]);
}
free(alphabet[j]);
}
free(alphabet);
free_network(net);
printf("All Done!\n");
system("pause");
首先将待处理的图像放入一个文件夹,例如作者将其放入
D盘的Ctext的picture下,作者只放了四张,如果有很多的话,可以用bat命令快速命名一下,方便处理。
步骤为,在当前文件夹下新建一个文本文件,复制粘贴以下代码,然后将后缀名改成bat,双击运行便可,效果为当前目录下所有jpg文件会从1开始自动排序。
@echo off
set a=00
setlocal EnableDelayedExpansion
for %%n in (*.jpg) do (
set /A a+=1
ren "%%n" "!a!.jpg"
)
接下来建立目标图片的绝对路径文本文件,编写一个小程序来快速建立。
#include
#include
using namespace std;
int main()
{
ofstream fout("D:\\Ctext\\input_image_list.txt");
int n;
printf("请输入数量:");
cin >> n;
for (int i = 1; i <= n; i++)
{
fout << "D:\\Ctext\\picture\\" <
把生成的exe文件拖到生成的文本旁边方便,并更改名称,日后方便使用。
效果如图所示:
回到darknet工程目录下面(记得第二步改完代码之后要运行哦!)
随便新建一个文本文件,里面写:
darknet_no_gpu.exe detector test cfg/coco.data cfg/yolov3.cfg yolov3.weights D:\Ctext\input_image_list.txt
保存,更改后缀为cmd,双击运行即开始处理。(作者的是tttttt.cmd)
代码解释:前面的darknet_no_gpu.exe,是我们更改代码后运行生成的程序,最后的D:\Ctext\input_image_list.txt 是我们第三步生成的目标图片绝对路径文本
最后效果如下:
picture文件夹是原本图片,pictest2是生成的图片
到这里就全部结束了,有什么问题可以留下评论,作者会在能力范围之内讨论,哈哈,我也不是什么大神,继续学习,与诸君共勉!