zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Opencv 4.1.0加载caffe crnn模型中错误纠正

Opencv错误 模型 加载 Caffe 4.1
2023-09-11 14:22:29 时间

1. 概述

最近倒腾了一下Opencv加载caffemodel做inference的事情,使用的模型是使用的crnn文本识别模型(仓库地址:链接),使用的Opencv版本是4.1.0。其中也遇到一些Opencv源码里面的问题,所以这里需要下载Opencv的源码自己使用CMake+VS2015编译(主要是方便问题定义与对应部分的修改…)。
在这里插入图片描述

2. 问题描述

对于Opencv中模型加载与输入数据的代码很简单了,这里就不贴了。直接来看看问题吧。问题描述:

OpenCV(4.1.0) Error: Assertion failed (Wh.rows == 4*Wh.cols) in cv::dnn::LSTMLayerImpl::LSTMLayerImpl, 
file D:\InstallDir\opencv\4.1.0\src\opencv-4.1.0\modules\dnn\src\layers\recurrent_layers.cpp, line 114

在上面已经把问题说得比较清楚了是因为LSTM权值参数的维度不匹配造成的,这里在配置好自己编译的Opencv(Debug版本带pdb文件),F11跟进去看看就知道了。

那么为毛会参数维度有问题呢?首先来看看Caffe中LSTM的权值参数是怎么存储的吧。

deploy = './deploy.prototxt'
caffe_model = './snapshot/_iter_100000.caffemodel'

net = caffe.Net(deploy, caffe_model, caffe.TEST)

lstm_param1 = net.params['lstm1'][0].data
lstm_param2 = net.params['lstm1'][1].data
lstm_param3 = net.params['lstm1'][2].data
print("lstm param1 shape:{}\n lstm param2 shape:{}\n lstm param3 shape:{}".format(lstm_param1.shape, lstm_param2.shape, lstm_param3.shape))

那么打印出来的参数维度如下:

lstm param1 shape:(500, 512) 	//输入的参数,index:0
lstm param2 shape:(500,)		//偏置的参数,index:1
lstm param3 shape:(500, 125)	//隐变量的参数,index:2

看到这里就很明白了,就是参数对应不上导致的,那么对应的解决办法就很简单了。

//line:96
public:

    LSTMLayerImpl(const LayerParams& params)
        : numTimeStamps(0), numSamples(0)
    {
        setParamsFrom(params);
        //添加下面两行
		std::swap(blobs[0], blobs[2]);
		std::swap(blobs[1], blobs[2]);
		......

至此,改动完成。重新编译之后再链接这个新生成的库就好了。

3. 思考

在使用Opencv之前先后使用了caffe cpu、tinydnn+eigen、ncnn(源码,非lib)的inference(什么AVX2之类的代码优化已做)。他们的结果表现如下(下面比较结果作为参考,不同环境与模型结果会有出入):

  • 1)caffe cpu:,其速度是这三者中最快的,但是其打包的是东西实在太多了(MKL可以加速矩阵运算);
  • 2)tinydnn:,其速度是三个里面相对来说比较慢的,初步分析是其内部的存储导致;
  • 3)ncnn:,其速度在3个里面排行第二个,不过这里没有使用valkan,不知道加上之后速度会提升多少;

这里使用Opencv运算的速度与caffe cpu相差无几,猜测其内部是使用OpenCL做加速,这里又是一个新坑了,值的细细研究了-_-||…