目录
1.caffe源码修改
2.caffe重新编译
3.模型转换
4.遇到的问题
因为官方 caffe1.x 框架不支持 yolo3/yolov4 的 upsample 层,所以需要手动增加 upsample 层,对 caffe 源码进行修改。
克隆 GitHub 上的转换工具项目:
git clone https://github.com/ChenYingpeng/darknet2caffe.git
将 darknet2caffe/caffe_layers/mish_layer 下的 mish_layer.hpp 文件和 darknet2caffe/caffe_layers/upsample_layer 下的 upsample_layer.hpp 拷贝到容器的路径:/opt/caffe/include/caffe/layers 下。
将 darknet2caffe/caffe_layers/mish_layer 下的 mish_layer.cpp、mish_layer.cu 文件和 darknet2caffe/tree/master/caffe_layers/upsample_layer 下的 upsample_layer.cpp、upsample_layer.cu 拷贝到容器的路径:/opt/caffe/src/caffe/layers/ 下。
将 darknet2caffe/caffe_layers/pooling_layer 下的 pooling_layer.cpp 拷贝到容器的路径:/opt/caffe/src/caffe/layers/ 下。
然后,打开容器内的 caffe 文件:/opt/caffe/src/caffe/proto/caffe.proto。按照如下说明修改相应字段的程序。
// LayerParameter next available layer-specific ID: 147 (last added: recurrent_param)
message LayerParameter {
optional TileParameter tile_param = 138;
optional VideoDataParameter video_data_param = 207;
optional WindowDataParameter window_data_param = 129;
++optional UpsampleParameter upsample_param = 149; //added by chen for Yolov3, make sure this id 149 not the same as before.
++optional MishParameter mish_param = 150; //added by chen for yolov4,make sure this id 150 not the same as before.
}
// added by chen for YoloV3
++message UpsampleParameter{
++ optional int32 scale = 1 [default = 1];
++}
// Message that stores parameters used by MishLayer
++message MishParameter {
++ enum Engine {
++ DEFAULT = 0;
++ CAFFE = 1;
++ CUDNN = 2;
++ }
++ optional Engine engine = 2 [default = DEFAULT];
++}
其中,++ 表示该行是增加的内容。
修改完 caffe 的一些源码之后,需要对 caffe 重新编译。
make clean
make all -j8
make pycaffe -j8
caffe 重新编译之后,就可以对 yolov3/yolov4 模型进行 caffe 转换了。
准备好我们已有的 yolov3 模型的配置文件和权重文件,例如:yolov3.cfg 和 yolov3.weights。在 darknet2caffe 目录下,输入以下命令:
python darknet2caffe.py ./yolov3.cfg ./yolov3.weights ./yolov3.prototxt ./yolov3.caffemodel
如果输出类似下面的语句,则证明转换成功!
I0522 10:19:19.015708 25251 net.cpp:228] layer1-act does not need backward computation.
I0522 10:19:19.015712 25251 net.cpp:228] layer1-scale does not need backward computation.
I0522 10:19:19.015714 25251 net.cpp:228] layer1-bn does not need backward computation.
I0522 10:19:19.015718 25251 net.cpp:228] layer1-conv does not need backward computation.
I0522 10:19:19.015722 25251 net.cpp:228] input does not need backward computation.
I0522 10:19:19.015725 25251 net.cpp:270] This network produces output layer139-conv
I0522 10:19:19.015731 25251 net.cpp:270] This network produces output layer150-conv
I0522 10:19:19.015736 25251 net.cpp:270] This network produces output layer161-conv
I0522 10:19:19.015911 25251 net.cpp:283] Network initialization done.
unknow layer type yolo
unknow layer type yolo
save prototxt to ./yolov3.prototxt
save caffemodel to ./yolov3.caffemodel
其中,yolov3.prototxt 和 yolov3.caffemodel 为转换后的 caffe 模型。
至此,yolov3/yolov4 转换为 caffe 模型完成
此时需要为其添加yolo层,共有两种类型
type1-example:
***********************************************************
layer {
bottom: "layer82-conv"
type: "Concat"
top: "layer83-yolo"
name: "layer83-yolo"
}
type2-example:
*************************************************************
layer {
bottom: "layer83-yolo"
bottom: "layer95-yolo"
bottom: "layer106-conv"
type: "Yolov3DetectionOutput"
top: "layer107-yolo"
name: "layer107-yolo"
yolov3_detection_output_param {
nms_threshold: 0.5
confidence_threshold: 0.1
num_classes: 10
biases: 10
biases: 13
biases: 16
biases: 30
biases: 33
biases: 23
biases: 30
biases: 61
biases: 62
biases: 45
biases: 59
biases: 119
biases: 59
biases: 119
biases: 92
biases: 106
biases: 156
biases: 198
mask: 6
mask: 7
mask: 8
mask: 3
mask: 4
mask: 5
mask: 0
mask: 1
mask: 2
mask_group_num: 3
anchors_scale: 32
anchors_scale: 16
anchors_scale: 8
}
}
4.1 没找到torch
pip install torch
4.2 没找到probuf
pip install probuf
4.3 KeyError: 'layer1-conv'
原作者环境为python2.7 + caffe + pytorch0.4
如果用python3的话按照如下修改
1)"需要修改convolution_param['pad'] = str(int(convolution_param['kernel_size'])/2) 为 convolution_param['pad'] = str(int(int(convolution_param['kernel_size'])/2)),否则产生的PAD可能为浮点"
2)
# print >> fp, 'name: \"%s\"' % props['name']
print('name: \"%s\"' % props['name'],file = fp)
change every "print" like this.
参考链接:
https://zhuanlan.zhihu.com/p/357316097