Caffe Windows系列(2): 使用C++ API进行分类

由于我的目标就是用Caffe来做图像的分类,而且是要用C++来做图像的分类。那么,目前最重要的事就是要验证一下能不能用Caffe做这件事,以及Caffe是怎么做这件事的。看到官网上提供了一个例子:Classifying ImageNet: using the C++ API。那我们就从这里开始吧。](http://caffe.berkeleyvision.org/gathered/examples/cpp_classification.html)。那我们就从这里开始吧。)

Caffe, at its core, is written in C++. It is possible to use the C++ API of Caffe to implement an image classification application similar to the Python code presented in one of the Notebook examples. To look at a more general-purpose example of the Caffe C++ API, you should study the source code of the command line tool caffe in tools/caffe.cpp.

A simple C++ code is proposed in examples/cpp_classification/classification.cpp.

也就是,官网说Caffe是完全可以用C++接口进行调用的。要想知道怎么调用,可以研究一下tools/caffe.cpp和examples/cpp_classification/classification.cpp这两个文件。按我目前的理解,tools/caffe.cpp是用来训练的,而classification.cpp则是教我们如何用已经训练好的模型进行分类。其实,对于caffe可以训练这件事是毋庸置疑的,只不过还没有深入了解。但现在最重要的,是要看看当模型训练完成之后,如何调用C++ API函数对图像进行识别。所以,本文章仅对examples/cpp_classification/classification.cpp这个文件感兴趣。网上已经有一个大神写了一篇关于这个议题的文章了,因此,我就只是在Windows系统上来重新实验一下吧。

目标

在Windows 7上实验对小猫图片(examples\images\cat.jpg)进行分类。

准备

我们需要准备三个文件:

  • caffemodel文件:可以直接在此地址下载,下载后放到models\bvlc_reference_caffenet文件夹下。
  • 均值文件: notepad++打开data/ilsvc12/get_ilsvrc_aux.sh,“编辑”->“文档格式转换”->“转换为UNIX格式”。在caffe目录下执行
data/ilsvc12/get_ilsvrc_aux.sh

执行并下载后,均值文件放在 data/ilsvrc12/ 文件夹里。

  • synset_words.txt文件
    在调用脚本文件下载均值的时候,这个文件也一并下载好了。里面放的是1000个类的名称。

C++实现

用Visual Studio打开Caffe.sln。生成examples\classification。如果生成的是Release版本,则生成的exe程序会在caffe\build\examples\cpp_classification\Release中。在控制台运行classification.exe,出现了Usage解释:

Usage: classification.exe deploy.prototxt network.caffemodel mean.binaryproto la
bels.txt img.jpg

也就是说一共需要五个参数:

  1. deploy.prototxt
  2. network.caffemodel
  3. mean.binaryproto
  4. labels.txt
  5. img.jpg
> cd caffe
> build\examples\cpp_classification\Release\classification.exe ^
  models\bvlc_reference_caffenet\deploy.prototxt ^
  models\bvlc_reference_caffenet\bvlc_reference_caffenet.caffemodel ^
  data\ilsvrc12\imagenet_mean.binaryproto ^
  data\ilsvrc12\synset_words.txt ^
  examples\images\cat.jpg

输出结果

---------- Prediction for examples\images\cat.jpg ----------
0.3134 - "n02123045 tabby, tabby cat"
0.2380 - "n02123159 tiger cat"
0.1235 - "n02124075 Egyptian cat"
0.1003 - "n02119022 red fox, Vulpes vulpes"
0.0715 - "n02127052 lynx, catamount"

即有0.3134的概率为tabby cat, 有0.2380的概率为tiger cat ......

OK,到此为止,说明用C++写程序来预测某一张图像属于哪个类是可用的。但如果真的自己要写的话,还是得仔细看一下classification.cpp。它一共有265行,我们就先来看一下它的main函数吧。

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];
  Classifier classifier(model_file, trained_file, mean_file, label_file);
 
  string file = argv[5];
 
  std::cout << "---------- Prediction for "
            << file << " ----------" << std::endl;
 
  cv::Mat img = cv::imread(file, -1);
  CHECK(!img.empty()) << "Unable to decode image " << file;
  std::vector predictions = classifier.Classify(img);
 
  /* Print the top N predictions. */
  for (size_t i = 0; i < predictions.size(); ++i) {
    Prediction p = predictions[i];
    std::cout << std::fixed << std::setprecision(4) << p.second << " - \""
              << p.first << "\"" << std::endl;
  }
}

line# 2-7: 显示用法信息
line# 9: 初始化glog……很惭愧,还没有使用过glog
line# 15: 初始化classifier对象。Classifier类是关键,也是在这个文件中定义的。
line# 22: 用OpenCV库读取图像
line# 24: 调用classifier的方法Classify,对刚刚读取的图像进行识别,并将结果存储在Prediction数组中,其中,Prediction的定义为

typedef std::pair Prediction;

键值对。
line# 27-31: 输出结果。

cpp除了main以外的其它地方就干了一件事:定义Classifier。等到真正要用的时候,我们可以把Classifier类直接拿来用。因此,暂时就不展开分析了。

总结

如果我们有了caffemodel文件均值文件synset_words.txt文件,则借助** Classifier类**,就可以实现简单地对OpenCV Mat图像预测,给出前n个预测结果。

你可能感兴趣的:(Caffe Windows系列(2): 使用C++ API进行分类)