使用环境:win10 64bits,VS2015,Opencv4.1.0
1. 概述
最近的几年Opencv开始在DNN领域耕耘,推出了网络inference的接口,其速度还是比较快的,特别是在本来就使用Opencv的图像处理代码中可以直接使用DNN模块直接加载model做inference,免除了添加附加依赖支持的问题。在4.1.0的版本中已经实现了将model从caffe、tensorflow、onnx等的导入。下面是这个版本中Opencv支持的网络层(cv::dnn::Layer)。
但是在实际使用过程中还是会出现层不支持的情况,这里使用caffe下的网络定义演示自定义层的定义,这里需要完成的功能是:通过添加一个DataNormLayer来完成不涉及参数加载的数据处理操作(图像归一化操作)。
2. custom layer的一些必要元素
dnn模块对应的文档:dnn文档
opencv给出的教程文档:custom layer tutorial
step1: 要添加自定义的层首先需要的就是将自定义的层继承自cv::dnn::Layer
,DataNormLayer是自定义层类名
class DataNormLayer : public cv::dnn::Layer
{
};
step2: 实现指定格式的类构造函数:
DataNormLayer(const cv::dnn::LayerParams ¶ms);
其中参数的定义为:
class CV_EXPORTS LayerParams : public Dict
{
public:
//TODO: Add ability to name blob params
std::vector<Mat> blobs; //存储模型layer的权值
String name; //layer的名称
String type; //layer的类型
};
step3: 定义实例创建静态函数:
static cv::Ptr<cv::dnn::Layer> create(cv::dnn::LayerParams& params)
{
return cv::Ptr<cv::dnn::Layer>(new DataNormLayer(params));
}
step4: 根据输入blob的大小计算输出blob的大小
virtual bool getMemoryShapes(const std::vector<std::vector<int> > &inputs,
const int requiredOutputs,
std::vector<std::vector<int> > &outputs,
std::vector<std::vector<int> > &internals) const CV_OVERRIDE;
step5: 在知道输入blob大小之后可以通过finalize来做一些操(optional):
virtual void finalize(cv::InputArrayOfArrays inputs_arr, cv::OutputArrayOfArrays outputs_arr) CV_OVERRIDE;
step6: 网络的前向传播forward,在内部定义数据的处理流程,并返回结果
virtual void forward(cv::InputArrayOfArrays inputs_arr,
cv::OutputArrayOfArrays outputs_arr,
cv::OutputArrayOfArrays internals_arr) CV_OVERRIDE;
step7: 将定义好的custom Layer进行注册