我正在尝试在iOS设备上使用.caffemodel
和OpenCV。我找到了这个github repository,但它只能用Xcode 6构建。我正在使用Xcode 7,但我也下载了Xcode 6,但仍然没有成功构建它。
如何在iOS 9上使用带有OpenCV的caffemodel?
PS:另一种选择是this,但是用swift&金属,我需要能够与OpenCV一起使用。
答案 0 :(得分:2)
您可以使用OpenCV DNN contrib module。
首先需要使用contrib模块构建OpenCV,您可以找到步骤here。
然后,您可以导入并使用this tutorial之后的.caffemodel
。
以下是本教程的更新版本,因为它不能正常工作:
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.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) */
void getMaxClass(dnn::Blob &probBlob, int *classId, double *classProb)
{
Mat probMat = probBlob.matRefConst().reshape(1, 1); //reshape the blob to 1x1000 matrix
Point classNumber;
minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
*classId = classNumber.x;
}
std::vector<String> readClassNames(const char *filename = "synset_words.txt")
{
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;
}
int main(int argc, char **argv)
{
cv::dnn::initModule();
String modelTxt = "bvlc_googlenet.prototxt";
String modelBin = "bvlc_googlenet.caffemodel";
String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
Ptr<dnn::Importer> importer;
try //Try to import Caffe GoogleNet model
{
importer = dnn::createCaffeImporter(modelTxt, modelBin);
}
catch (const cv::Exception &err) //Importer can throw errors, we will catch them
{
std::cerr << err.msg << std::endl;
}
if (!importer)
{
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);
}
dnn::Net net;
importer->populateNet(net);
importer.release(); //We don't need importer anymore
Mat img = imread(imageFile);
if (img.empty())
{
std::cerr << "Can't read image from the file: " << imageFile << std::endl;
exit(-1);
}
resize(img, img, Size(224, 224)); //GoogLeNet accepts only 224x224 RGB-images
dnn::Blob inputBlob = dnn::Blob(img); //Convert Mat to dnn::Blob batch of images
net.setBlob(".data", inputBlob); //set the network input
net.forward(); //compute output
dnn::Blob prob = net.getBlob("prob"); //gather output of "prob" layer
int classId;
double classProb;
getMaxClass(prob, &classId, &classProb);//find the best class
std::vector<String> classNames = readClassNames();
std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
std::cout << "Probability: " << classProb * 100 << "%" << std::endl;
return 0;
} //main
答案 1 :(得分:1)
我将发布另一个答案,因为与最新版本有所不同。
首先dnn
已经在标准OpenCV库中,因此您不必从contrib_modules
进行构建。
加载网络的功能是readNetFromCaffe
。
例如,以下代码加载NN:
std::string modelName = "path/to/mymodel.caffemodel";
std::string protoName = "path/to/deploy.prototxt";
cv::dnn::Net net;
try
{
net = cv::dnn::readNetFromCaffe(protoName, modelName);
}
catch (cv::Exception& e)
{
std::cerr << "Exception: " << e.what() << std::endl;
if (net.empty())
{
std::cerr << "Can't load network by using the following files: " << std::endl;
std::cerr << "prototxt: " << protoName << std::endl;
std::cerr << "caffemodel: " << modelName << 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);
}
}
然后您可以运行NN:
cv::Mat res_mat;
float res;
cv::Mat inputBlob = cv::dnn::blobFromImage(roi, 1.0f, cv::Size(227, 227),
cv::Scalar(0, 0, 0), false);
net.setInput(inputBlob);
//During the forward pass output of each network layer is computed,
//but in this example we need output from "prob" layer only.
res_mat = net.forward("score");
std::cout<<res_mat<<std::endl;
res_mat = res_mat.reshape(1, 1); //reshape the blob to 1x2 matrix
return res_mat.at<float>(0);
函数cv::dnn::blobFromImage
将图像调整为第三个参数(在我的情况下为cv::Size(227, 227)
)中指定的输入网络大小。参数cv::Scalar(0, 0, 0)
是从三个BGR
通道中减去均值。
score
是我使用的NN中输出层的名称。您可以在prototxt
文件中看到此信息。