首先感谢AlexeyAB大神提供的YOLOv4源码,以及gmayday1997大神提供的split以及shuffle模块源码,本文以两位的工作进行yolov4版本中轻量化模块shufflenet模块的添加。
①首先寻找到channel_slice.c和channel_shuffle.c的源文件及.h头文件,以及加入split.c与split.h六个文件。
②接下来添加新层。参考DarkNet(1)--添加新层教程(slice层为例)
2.1 makefile文件的154行OBJ=中添加channel_slice.o,channel_shuffle.o和split.o。
include/darknet.h文件中添加相应的层名字
// layer.h
typedef enum {
…
CHANNEL_SHUFFLE,
CHANNEL_SLICE,
SPLIT,
…
}
2.2 添加新函数中相应参数的名字
// layer.h
struct layer {
…
int axis; // added by fht 2021/03/22
int begin_slice_point;// added by fht 2021/03/22
int end_slice_point;// added by fht 2021/03/22
…
}
③src/parser.c文件中,引用文件添加
#include "split.h"
#include "channel_shuffle.h"
#include "channel_slice.h"
layer_type结构中加入
LAYER_TYPE string_to_layer_type(char * type)
{……
if (strcmp(type, "[channel_shuffle]") == 0) return CHANNEL_SHUFFLE;
if (strcmp(type, "[channel_slice]") == 0) return CHANNEL_SLICE;
if (strcmp(type, "[split]") == 0) return SPLIT;
……
}
并在文件中加入三个释意函数:
layer parse_split(list *options,size_params params,network net){
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch = params.batch;
char *l = option_find(options,"from");
if(!l) error("Split Layer must specify input layers");
int index = atoi(l);
if(index <0) index = params.index + index;
layer from = net.layers[index];
layer layer_ = make_split_layer(batch,from.out_w,from.out_h,from.out_c,index);
return layer_;
}
channel_slice_layer parse_channel_slice(list *options,size_params params,\
network net){
int batch,h,w;
h = params.h;
w = params.w;
//c = params.c;
batch = params.batch;
char *l = option_find(options,"from");
int len = strlen(l);
if(!l) error("Channel Slice Layer must specify input layers");
int begin_slice_point = option_find_int(options,"start",2);
int end_slice_point = option_find_int(options,"end",2);
int axis = option_find_int(options,"axis",1);
int n = 1;
int *layers = (int*)calloc(n,sizeof(int));
int* sizes = (int*)calloc(n, sizeof(int));
int *c = (int*)calloc(n, sizeof(int));
for(int i = 0; i < n; ++i){
int index = atoi(l);
l = strchr(l, ',')+1;
if(index < 0) index = params.index + index;
layers[i] = index;
sizes[i] = net.layers[index].outputs;
c[i] = net.layers[index].out_c;
}
channel_slice_layer layer_ = make_channel_slice_layer(batch,w,h,c[0],begin_slice_point,\
end_slice_point,axis, n, layers,sizes);
return layer_;
}
layer parse_channel_shuffle(list *options,size_params params){
int batch,h,w,c;
h = params.h;
w = params.w;
c = params.c;
batch = params.batch;
int groups = option_find_int(options,"groups",2);
layer l = make_channel_shuffle_layer(batch,w,h,c,groups);
return l;
}
在network parse_network_cfg_custom(char *filename, int batch, int time_steps)的while(n)循环结构中,加入层选项
while(n){
params.index = count;
fprintf(stderr, "%4d ", count);
s = (section *)n->val;
options = s->options;
layer l = { (LAYER_TYPE)0 };
LAYER_TYPE lt = string_to_layer_type(s->type);
if(lt == CHANNEL_SHUFFLE){
l = parse_channel_shuffle(options,params);
}else if(lt == CHANNEL_SLICE){
l = parse_channel_slice(options,params,net);
}else if(lt == SPLIT){
l = parse_split(options,params,net);
}
…………
④src/network.c文件添加如下代码:
#include "split.h"
#include "channel_shuffle.h"
#include "channel_slice.h"
char *get_layer_string(LAYER_TYPE a)
{
switch(a){
……
case CHANNEL_SHUFFLE:
return "channel_shuffle";
case CHANNEL_SLICE:
return "channel_slice";
case SPLIT:
return "split";
……
}
}
在int resize_network(network *net, int w, int h)函数中加入:(split.c函数没有用到,并且存在报错,目前并未解决,可以进行尝试)
else if (l.type == CHANNEL_SHUFFLE) {
resize_channel_shuffle_layer(&l, w, h);
}else if (l.type == CHANNEL_SLICE) {
resize_channel_slice_layer(&l, w, h);
}
⑤需要用到GPU的(CPU未进行验证),还需要对blas.h文件进行一个添加,否则会出现调用错误:
void channel_shuffle_ongpu(int N, float* output, float* input, int group_row, int group_column, int feature_map_size, int len);
void channel_slice_ongpu(int count, float* output, float* input, int batch_size, int spatial_size, int input_slice_axis, int output_slice_axis, int begin_slice_axis, int bForward);
⑥按照官方代码进行cmake、编译即可。
编译yolo_cpp_dll。
采用文本编译器,记事本、atom、notebook都可
<ClCompile Include="..\..\src\yolo.c" />
<ClCompile Include="..\..\src\yolo_layer.c" />
<CudaCompile Include="..\..\src\channel_shuffle.c">
<CudaCompile Include="..\..\src\channel_shuffle.h" />
<CudaCompile Include="..\..\src\channel_slice.h" />
<CudaCompile Include="..\..\src\split.h" />
所有新加入的文件,右击文件---》属性---》常规---》项目类型选择CUDA C/C++,否则会出现链接器错误的问题。
然后按照正常编译即可。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)