C++ 使用 caffemodel
首先列出了一些参照的文章,但是自己并没有完全按照这些配置,但是有重要参考价值。
重要参照link(优先级从上到下):
1. vs2013创建caffe工程
2. caffe-Windows 添加工程-以classification为例,这里面还有其他几个有用的链接。
正式开始配置环境
-
已经配置好了caffe的基本环境,包括使用python的“import caffe”不出错,可按照https://blog.csdn.net/woha1yo/article/details/117473594配置 Debug和Release环境,并且libraries_v140_x64_py35_1.1.0.tar.bz2已经解压至对应目录“C:\Users\MWG.caffe\dependencies\libraries_v140_x64_py35_1.1.0\libraries”,后续会用到,下载地址为https://pan.baidu.com/s/1qYdrSE4#list/path=%2F。
-
使用VS2015新建空项目“cpp_classification”;拷贝文件cpp_classification.cpp(地址caffe-window/examples/cpp_classification目录下)至VS2015新建的目录下;右键源文件添加现有项,选中“classification.cpp”。
-
调整配置为“Realease、x64”
-
配置包含目录(include),库目录(lib)和附加依赖项(xxx.lib)
-
包含目录,VC++目录 -> 包含目录
-
添加caffe-window的包含目录
D:\caffe-windows\include
-
使用protoc.exe生成,并拷贝到对应目录下, 使用目录
C:\Users\MWG\.caffe\dependencies\libraries_v140_x64_py35_1.1.0\libraries\bin
下的 protoc.exe,将其拷贝至目录
D:\caffe-windows\src\caffe\proto
并新建makefile.bat文件,内容为
protoc.exe caffe.proto --cpp_out=.\ pause
保存之后,直接运行,该bat会将caffe.proto生成 caffe.pb.cc和caffe.pb.h。注意protoc.exe的版本不能太高,否则会出错,最好就是编译caffe时的版本最好,否则后面的libboost_xxx的版本对应不上。
之后将生成的caffe.pb.cc和caffe.pb.h拷贝至目录(D:\caffe-windows\include\caffe\proto)下:
-
添加boost的包含目录
C:\Users\MWG\.caffe\dependencies\libraries_v140_x64_py35_1.1.0\libraries\include\boost-1_61
-
添加其他依赖的包含目录
C:\Users\MWG\.caffe\dependencies\libraries_v140_x64_py35_1.1.0\libraries\include
-
若加入了预处理的宏定义
USE_OPENCV
CPU_ONLY
添加两个预处理宏,更多预定义的宏添加
则不需要添加cuda的包含目录,否则需要加入cuda的包含目录和库目录,分别为C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\include
和C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0\lib\x64
。 -
Opencv库自己的电脑已经安装并配置
-
最终包含目录(include)为:
-
库目录, VC++目录 -> 库目录 添加
C:\Users\MWG\.caffe\dependencies\libraries_v140_x64_py35_1.1.0\libraries\lib
在编译的时候系统会提示无法打开lib*.lib文件(例如,无法打开文件“libboost_date_time-vc140-mt-1_61.lib”),我的系统中主要是boost中的一些lib。其实这些lib在文件夹中是存在的只是命名的方式不对。将库文件夹中对应的lib文件前面加上lib三个字母就可以了。
-
例如我的系统中提示找不到libboost_date_time-vc140-mt-1_61.lib,在同一个文件夹中创建一个副本并重新命名为libboost_date_time-vc140-mt-1_61.lib就行了。
-
还有另外一个,将“boost_filesystem-vc140-mt-1_61.lib”复制一份,并重命名为"libboost_filesystem-vc140-mt-1_61.lib"。
-
-
添加caffe.lib的Release版本包含目录,
D:\caffe-windows\scripts\build\lib\Release
并在附加依赖项中加入
caffe.lib
-
Opencv库自己的电脑已经安装并配置
-
总的库目录(lib)
-
附加依赖项,链接器 -> 输入 -> 附加依赖项 添加
根据D:\caffe-windows\scripts\build\examples\cpp_classification\Release
目录下的DLL依赖文件名称,在附加依赖中添加对应的lib名。
例如,
-
总的附加依赖项
caffe.lib caffeproto.lib python35.lib gflags.lib glog.lib libprotobuf.lib libprotoc.lib opencv_world3411.lib boost_chrono-vc140-mt-1_61.lib boost_filesystem-vc140-mt-1_61.lib boost_python-vc140-mt-1_61.lib boost_system-vc140-mt-1_61.lib boost_thread-vc140-mt-1_61.lib caffehdf5.lib caffehdf5_hl.lib caffezlib.lib libopenblas.dll.a
其中,libprotoc.lib可以不要,或许还有一两个包可以不要,dont mind。
此时已经能够编译成功。
--------------------------------------------------------------漂亮的分界线------------------------------------------------
- 修改classification.py文件,传入测试数据的位置
int main(int argc, char** argv) { /* if (argc != 6) { std::cerr << "Usage: " << argv[0] << " deploy.prototxt network.caffemodel" << " mean.binaryproto labels.txt img.jpg" << std::endl; return 1; } */ ::google::InitGoogleLogging(argv[0]); /* string model_file = argv[1]; string trained_file = argv[2]; string mean_file = argv[3]; string label_file = argv[4]; string file = argv[5]; */ // mwg string model_file = "D:/caffeProjects/cifar/cifar10_quick.prototxt"; string trained_file = "D:/caffeProjects/cifar/cifar10_quick_iter_4000.caffemodel.h5"; string mean_file = "D:/caffeProjects/cifar/mean.binaryproto"; string label_file = "D:/caffeProjects/cifar/synset_words.txt"; string file = "D:/caffeProjects/cifar/dog.jpg"; Classifier classifier(model_file, trained_file, mean_file, label_file); std::cout << "---------- Prediction for " << file << " ----------" << std::endl;
-
按照下面问题5,6修改代码,layer的加入与注册。
-
下载测试数据,后面链接网盘中目录的 “caffeProjects/cifar”
链接:http://pan.baidu.com/s/1skIfYkH 密码:w69a
-
测试成功!😃
cifar的结果:
mnist的结果:
可能出现的错误
-
无法解析的外部符号 “public: void __cdecl caffe::Blob::FromProto(class caffe::BlobProto const &,bool)”
答:此类问题一般是由于缺失对应的lib包造成的,解决方案为在库目录和附加依赖项中添加进去正确的依赖包,本问题添加caffe.lib即可。 -
无法打开文件“python35.lib”
答:由于自己的电脑默认python环境不是conda,而是另一个python3.6,所以可能系统无法找到对应的包。解决方案为在库目录和附加依赖项中添加进去正确的依赖包。在目录D:\miniconda3\envs\caffe\libs
下的python35.lib包。 -
无法解析的外部符号 “public: virtual __cdecl caffe::BlobProto::~BlobProto(void)”
答:此类问题一般是由于缺失对应的lib包造成的,解决方案为在附加依赖项中添加进去正确的依赖包。本问题添加caffeproto.lib即可。 -
无法解析的外部符号 “__declspec(dllimport) public: class std::basic_string<char,struct std::char_traits,class std::allocator > * __cdecl google::base::CheckOpMessageBuilder::NewString(void)”
答:此类问题一般是由于缺失对应的lib包造成的,解决方案为在附加依赖项中添加进去正确的依赖包。本问题添加caffeproto.lib即可。 -
layer_factory.cpp:62] Check failed: registry.count(type) == 1 (0 vs. 1) Unknown layer type: Input (known types: Convolution, Eltwise, LRN, Pooling, Power, Python, ReLU, Sigmoid, Softmax, Split, TanH)
*** Check failure stack trace: ***
答: 参考博客。 大概是libcaffe.lib是静态库的方式编译的,有一些东西没法使用。解决方案就是,新建一个头文件,例如head.h,将他提示你没有的层的头文件包含进去,在添加类似于extern INSTANTIATE_CLASS(InputLayer);的这句话
后来发现有的层添加了也会报错,那是因为他们没有类似于REGISTER_LAYER_CLASS(Input);这句话。可以想象,
REGISTER_LAYER_CLASS这句话作用就是注册layer。可以添加进去。贴上自己的head.h,添加了使用到的layer。#include "caffe/common.hpp" #include "caffe/layers/input_layer.hpp" #include "caffe/layers/inner_product_layer.hpp" #include "caffe/layers/dropout_layer.hpp" #include "caffe/layers/conv_layer.hpp" #include "caffe/layers/relu_layer.hpp" #include "caffe/layers/pooling_layer.hpp" #include "caffe/layers/lrn_layer.hpp" #include "caffe/layers/softmax_layer.hpp" namespace caffe { extern INSTANTIATE_CLASS(InputLayer); extern INSTANTIATE_CLASS(InnerProductLayer); extern INSTANTIATE_CLASS(DropoutLayer); extern INSTANTIATE_CLASS(ConvolutionLayer); REGISTER_LAYER_CLASS(Convolution); extern INSTANTIATE_CLASS(ReLULayer); REGISTER_LAYER_CLASS(ReLU); extern INSTANTIATE_CLASS(PoolingLayer); REGISTER_LAYER_CLASS(Pooling); extern INSTANTIATE_CLASS(LRNLayer); REGISTER_LAYER_CLASS(LRN); extern INSTANTIATE_CLASS(SoftmaxLayer); REGISTER_LAYER_CLASS(Softmax); }
之后在
classification.cpp
中include该头文件# include "head.h"
-
layer_factory.cpp:48] Check failed: registry.count(type) == 0 (1 vs. 0) Layer type Convolution already registered.
答:删掉对应extern INSTANTIATE_CLASS 后面的REGISTER_LAYER_CLASS。