darknet添加新层以编译yolo_cpp_dll-------shufflenet模块

首先感谢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.osplit.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++,否则会出现链接器错误的问题。 

然后按照正常编译即可。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值