Darknet卷基层浅层特征可视化教程

(3) 2024-08-27 08:23

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
Darknet卷基层浅层特征可视化教程,希望能够帮助你!!!。

Darknet浅层可视化教程

目录
  • Darknet浅层可视化教程
    • 说明
    • 处理步骤
    • 使用python可视化txt文件

说明

针对YOLO官方提供的c语言版的darknet进行了修改,添加了一些函数,进行可视化处理。

建议使用visual studio code进行代码的跟踪和调试。

可视化内容是针对一下命令,对一张图片进行可视化:

./darknet detector test cfg/voc.data data/yolov3-voc.cfg backup/yolov3-voc_40000.weights 

处理步骤

  • 入口: darknet.c的main文件,找到以下声明:
} else if (0 == strcmp(argv[1], "detector")){ run_detector(argc, argv); 
  • 进入run_detector函数,在detector.c文件中找到以下代码:
if(0==strcmp(argv[2], "test")) test_detector(datacfg, cfg, weights, filename, thresh, hier_thresh, outfile, fullscreen); else if(0==strcmp(argv[2], "train")) train_detector(datacfg, cfg, weights, gpus, ngpus, clear); else if(0==strcmp(argv[2], "valid")) validate_detector(datacfg, cfg, weights, outfile); else if(0==strcmp(argv[2], "valid2")) validate_detector_flip(datacfg, cfg, weights, outfile); else if(0==strcmp(argv[2], "recall")) validate_detector_recall(datacfg, cfg, weights); else if(0==strcmp(argv[2], "demo")) { 
  • 找到第二个参数“test”对应的函数: test_detector,进入该函数进行修改:
while(1){ if(filename){ strncpy(input, filename, 256); image im = load_image_color(input,0,0); image sized = letterbox_image(im, net->w, net->h); layer l = net->layers[net->n-1]; float *X = sized.data; time=what_time_is_it_now(); network_predict(net, X); printf("%s: Predicted in %f seconds.\n", input, what_time_is_it_now()-time); int nboxes = 0; detection *dets = get_network_boxes(net, im.w, im.h, thresh, hier_thresh, 0, 1, &nboxes); 
  • 很明显,network_predict函数就是用来让图片在网络中forward_gpu一下,然后得到结果,所以进入该函数:
float *network_predict(network *net, float *input) { network orig = *net; net->input = input; net->truth = 0; net->train = 0; net->delta = 0; forward_network(net); float *out = net->output; *net = orig; return out; } 
  • 再继续找核心函数forward_network(net)
void forward_network(network *netp) { #ifdef GPU if(netp->gpu_index >= 0){ forward_network_gpu(netp); return; } #endif network net = *netp; printf("haha, net layer number: %d\n",net.n); int i; for(i = 0; i < net.n; ++i){ //image imi = get_network_image(netp); //save_image(imi,"thiisisatest"); net.index = i; layer l = net.layers[i]; if(l.delta){ fill_cpu(l.outputs * l.batch, 0, l.delta, 1); } l.forward(l, net); net.input = l.output; if(l.truth) { net.truth = l.output; } } calc_network_cost(netp); } 
  • 由于本项目是在有GPU支持的情况下,所以会执行#ifdef和#endif之间的内容,继续找forward_network_gpu()函数。
void forward_network_gpu(network *netp) { network net = *netp; cuda_set_device(net.gpu_index); cuda_push_array(net.input_gpu, net.input, net.inputs*net.batch); if(net.truth){ cuda_push_array(net.truth_gpu, net.truth, net.truths*net.batch); } int i; for(i = 0; i < net.n; ++i){ net.index = i; layer l = net.layers[i]; if(l.delta_gpu){ fill_gpu(l.outputs * l.batch, 0, l.delta_gpu, 1); } l.forward_gpu(l, net); net.input_gpu = l.output_gpu; net.input = l.output; if(l.truth) { net.truth_gpu = l.output_gpu; net.truth = l.output; } //这个函数是新加的,用来得到图片保存图片 image tmp = get_network_cow_image_layer(&net,i); } pull_network_output(netp); calc_network_cost(netp); } 
  • 该函数在network.c文件中声明,需要在darknet.h中提前声明该函数:
image get_network_cow_image_layer(network *net, int i); 

具体内容如下:

image get_network_cow_image_layer(network *net, int i) { layer l = net->layers[i]; #ifdef GPU cuda_pull_array(l.output_gpu, l.output, l.outputs); #endif printf("w:%d,h:%d,c:%d\n",l.out_w,l.out_h,l.out_c); if (l.out_w && l.out_h && l.out_c){ return float_to_cow_image(l.out_w,l.out_h,l.out_c,l.output,i); } image def = {0}; return def; } 
  • 可以发现,float_to_cow_image也是新加的函数,也需要加入到darknet.h中去:
image get_network_cow_image_layer(network *net, int i); 

该函数具体内容如下(参考get_network_image_layer进行修改,添加i是为了识别这是第几层的可视化,用于保存文件):

/***************************************************** *func: 主要是为了将output结果能够映射到0-255区间(初始化,使用sigmoid函数进行归一化,),便于进行可视化操作。 将所有维度合成到一个维度,然后取平均,×255,便于查看 *****************************************************/ image float_to_cow_image(int w, int h, int c, float *data,int ai) { char tp[1000]; //保存文件到特定文件夹(feature_txt)中并根据ai大小命名 sprintf(tp,"/home/learner/darknet/feature_txt/out_%d.txt",ai); FILE * stream = fopen(tp,"w+"); //创建一个1维的空图片 image out = make_empty_image(w,h,1); int i, j; //设计一个数组保存该图片内容 float * tempData = calloc(w*h,sizeof(float)); //初始化 for(i = 0 ; i < w*h ; i++) { tempData[i] = 0; } //归一化,sigmoid for(i = 0 ; i < w*h*c ; i++) { data[i] = 1.0/(1+exp(-1*data[i])); } //合并通道 for(i = 0 ; i < w*h ; i++) { for(j = 0 ; j < c ; j++) { tempData[i] += data[i+j*w*h]; } } //保存到文件 for(i = 0 ; i < w*h; i++) { tempData[i] /= c; tempData[i] *= 255; fprintf(stream," %f",tempData[i]); if((i+1)%w==0) fprintf(stream,"\n"); } //关闭文件流 fclose(stream); out.data = tempData; return out; } 

重新make,运行命令,会在指定目录下得到txt文件,之后的操作就是需要将txt文件可视化为图片。

使用python可视化txt文件

使用python读取图片有一个好处,就是可以将灰度图转化为热力图,这样更容易观察,否则会认为生成了一系列噪音点。

具体代码如下:(需要matplotlib,PIL, numpy库)

#!/home/learner/miniconda3/bin/python # -*- coding: utf-8 -*- """ Spyder Editor This is a temporary script file. """ import os import matplotlib.pyplot as plt import numpy as np from PIL import Image def process(filepath,outpath): for fileName in os.listdir(filepath): print(fileName) print(filepath+"/"+fileName) a=np.loadtxt(filepath+"/"+fileName) im = Image.fromarray(np.uint8(a)) #tmp_img = plt.imshow(im) #tmp_img.set_cmap('hsv') #plt.show() print(im.size) #im.set_cmap('hot') #plt.figure(figsize=(15,15)) plt.title(fileName) plt.imshow(im),plt.axis('off') im.save(outpath+"/"+fileName[:-4]+".jpg") #plt.savefig(outpath+"/"+fileName[:-4]+".jpg",bbox_inches="tight",transparent=True,pad_inches=0) if __name__ == "__main__": outpath = "/home/learner/darknet/feature_pic" filepath="/home/learner/darknet/feature_txt" process(filepath,outpath) 

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

上一篇

已是最后文章

下一篇

已是最新文章

发表回复