Foch155

导航

使用VS+OpenCV调用深度学习模型

最近项目有个任务,要在windows环境下用VS+OpenCV实现caffe模型的调用,于是在网上找了几个相关的博客跑了几个demo练练手。这些博客写得都很详细,但是有些细节由于版本更新的问题,配置的过程中有些变化,所以自己再发篇博客记录下。目前OpenCV似乎只支持对caffe模型的调用,如果手上有的是pytorch或者tensorflow训练好的模型的话,可以用其他软件转成caffemodel以及protxt文件。

 

之前尝试过用OpenCV3.2.0,所做的工作如下:

前期的准备工作可以参考这篇博客:基于opencv dnn模块 的caffe模型的调用,关于配置环境,我用的VS2015,CMake是官网的最新版本,OpenCV选的是博客中用的OpenCV3.2.0。其中需要注意的是,运行环境及前期准备过程中, OpenCV contrib库的版本应该与自己下载的OpenCV库相对应,不然后续编译的过程中会报错。同时,在编译OpenCV及contrib库的过程中,在完成第一次编译,找到“OPENCV_EXTRA_MODUALS_PATH”设置路径的时候,在复制完路径后记得把路径中的‘\’改成'/',不然也会报错。接下来就是按着上面的博客一步步来。第一demo很顺利地就跑通了,到第二个demo的最后一步的时候,系统总是会报错,提示我没有'norm_para'这个参数。用博客上的方法发现还是跑不通,原因可能是网上下的caffemode时有更新,所以deploy.protxt中也会有相应的改动,在网上找了好久一直没有解决的办法,最终靠着github解决了问题:https://github.com/opencv/opencv_contrib/issues/935

 

后来调用caffe训练的模型的时候,发现OpenCV3.2.0的dnn模块还不支持bn层,而对于很多网络来说,缺少了bn层,测试效果往往会下降很多。折腾了好半天,发现OpenCV3.3.0已经新加入了bn层,并且将dnn提升到了正式代码块中,也就省去了前面提到的用CMake进行编译的过程。下面直接贴一段调用caffe模型,输出网络某一层的函数的代码:

#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/trace.hpp>
using namespace cv;
using namespace cv::dnn;

float* classifier(string modelTxt, string modelBin, string img_path)
{

	Mat testImage = imread(img_path, 0);

	if (testImage.empty()) {

		printf("could not load image...\n");


	}

	// create googlenet with caffemodel text and bin
	Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
	if (net.empty())

	{

		std::cerr << "Can't load network by using the following files: " << std::endl;

		std::cerr << "prototxt:   " << modelTxt << std::endl;

		std::cerr << "caffemodel: " << modelBin << std::endl;

	

	}
	Mat inputBlob = blobFromImage(testImage, 1);
	Mat InnerProduct1;
	cv::TickMeter t;
	CV_TRACE_REGION("forward");
	net.setInput(inputBlob, "data");        //set the network input
	t.start();
	InnerProduct1 = net.forward("Pooling3");                          //compute output
	t.stop();
	float *b;
	b = new float[64];

	for (int i = 0; i < 64; i++)
	{
		//b[i] = InnerProduct1.at<float>(i);
		b[i] = InnerProduct1.at<float>(0,i,0);
	}
	//cout << b[1];
	return b;
}

 其中函数的输入modelTxt与modelBin分别对应于caffe的prototxt文件以及训练好的caffemodel,img_path为要测试的图片,而"Pooling3"对应于你想提取的某一层在prototxt文件中的名称。

 

posted on 2018-05-02 11:21  Foch155  阅读(1268)  评论(0编辑  收藏  举报