opencv在3.0之后就支持调用深度学习模型。OpenCV dnn模块目前支持Caffe、TensorFlow、Torch、PyTorch等深度学习框架。另外,新版本中使用预训练深度学习模型的API同时兼容C++和Python。
参照官方教程进行一个分类模型的调用caffe模型进行分类,Load Caffe framework models。注意版本,我的版本是3.4.1,选择对应版本。
image.png
-
在opencv的解压文件下面有sample/dnn/所有的例子。这个例子来自sample/dnn//caffe_googlenet.cpp
-
下载两个文件bvlc_googlenet.prototxt and bvlc_googlenet.caffemodel
3.也要下载 synset_words.txt.
-
把上面三个文件放在与caffe_googlenet.cpp同级目录。
-
新建工程把caffe_googlenet.cpp添加进去。
caffe_googlenet.cpp 代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | #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; #include <fstream> #include <iostream> #include <cstdlib> using namespace std; /* Find best class for the blob (i. e. class with maximal probability) */ static void getMaxClass(const Mat &probBlob, int *classId, double *classProb) { Mat probMat = probBlob.reshape(1, 1); //reshape the blob to 1x1000 matrix Point classNumber; minMaxLoc(probMat, NULL, classProb, NULL, &classNumber); *classId = classNumber.x; } static std::vector<String> readClassNames(const char *filename) { std::vector<String> classNames; std::ifstream fp(filename); if (!fp.is_open()) { std::cerr << "File with classes labels not found: " << filename << std::endl; exit(-1); } std::string name; while (!fp.eof()) { std::getline(fp, name); if (name.length()) classNames.push_back(name.substr(name.find(' ') + 1)); } fp.close(); return classNames; } const char* params = "{ help | false | Sample app for loading googlenet model }" "{ proto | bvlc_googlenet.prototxt | model configuration }" "{ model | bvlc_googlenet.caffemodel | model weights }" "{ label | classification_classes_ILSVRC2012.txt | names of ILSVRC2012 classes }" "{ image | space_shuttle.jpg | path to image file }" "{ opencl | false | enable OpenCL }" ; int main(int argc, char **argv) { CV_TRACE_FUNCTION(); CommandLineParser parser(argc, argv, params); if (parser.get<bool>("help")) { parser.printMessage(); return 0; } String modelTxt = parser.get<string>("proto"); String modelBin = parser.get<string>("model"); String imageFile = parser.get<String>("image"); String classNameFile = parser.get<String>("label"); Net net; try { //! [Read and initialize network] net = dnn::readNetFromCaffe(modelTxt, modelBin); //! [Read and initialize network] } catch (const cv::Exception& e) { std::cerr << "Exception: " << e.what() << std::endl; //! [Check that network was read successfully] 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; std::cerr << "bvlc_googlenet.caffemodel can be downloaded here:" << std::endl; std::cerr << "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" << std::endl; exit(-1); } //! [Check that network was read successfully] } if (parser.get<bool>("opencl")) { net.setPreferableTarget(DNN_TARGET_OPENCL); } //! [Prepare blob] Mat img = imread(imageFile); if (img.empty()) { std::cerr << "Can't read image from the file: " << imageFile << std::endl; exit(-1); } //GoogLeNet accepts only 224x224 BGR-images Mat inputBlob = blobFromImage(img, 1.0f, Size(224, 224), Scalar(104, 117, 123), false); //Convert Mat to batch of images //! [Prepare blob] net.setInput(inputBlob, "data"); //set the network input Mat prob = net.forward("prob"); //compute output cv::TickMeter t; for (int i = 0; i < 10; i++) { CV_TRACE_REGION("forward"); //! [Set input blob] net.setInput(inputBlob, "data"); //set the network input //! [Set input blob] t.start(); //! [Make forward pass] prob = net.forward("prob"); //compute output //! [Make forward pass] t.stop(); } //! [Gather output] int classId; double classProb; getMaxClass(prob, &classId, &classProb);//find the best class //! [Gather output] //! [Print results] std::vector<String> classNames = readClassNames(classNameFile.c_str()); std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl; std::cout << "Probability: " << classProb * 100 << "%" << std::endl; //! [Print results] std::cout << "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " << t.getCounter() << " iterations)" << std::endl; // input samething int a; std::cin >> a; return 0; } //main |
按照对应的版本使用例子,一般不会出错。
这里有几个比较重要的参数,需改对应的参数就可进行不同图片的分类了。
1 2 3 4 5 6 7 | const char* params = "{ help | false | Sample app for loading googlenet model }" "{ proto | bvlc_googlenet.prototxt | model configuration }" "{ model | bvlc_googlenet.caffemodel | model weights }" "{ label | synset_words.txt | names of ILSVRC2012 classes }" "{ image | space_shuttle.jpg | path to image file }" "{ opencl | false | enable OpenCL }" |
proto: caffe的配置文件
model:caffe的参数文件
image:图片
opencl:是否使用opencl进行加速
result
1 2 3 4 5 6 7 8 9 | Attempting to upgrade input file specified using deprecated V1LayerParameter: bvlc_googlenet.caffemodel Successfully upgraded file specified using deprecated V1LayerParameter [ INFO:0] Initialize OpenCL runtime... Net Outputs(1): prob Best class: #812 'shuttle' Probability: 99.993% Time: 1492.05 ms (average from 10 iterations) |
使用c++ opencv调用tensorflow训练好的卷积神经网络
opencv官方教程caffe model调用
OpenCV调用TensorFlow预训练模型
基于opencv dnn模块 的caffe模型的调用