opencv3.4.3调用caffe分类模型

前言

opencv是图像领域中非常优秀的一个开源库,近年来,随着深度学习的发展,深度在图像识别、物体检测、语义分割等领域已经达到落地的程度。opencv开源库也一直在支持各种分类、检测model的调用,虽然还不够全面。。。opencv从3.3开始已经支持分类模型的调用,包括caffe、tensorflow、pytorch等框架训练出的模型。从3.4.2开始,支持yolov3的调用,这真的是一个很大的进步,可以把物体检测真正落地。

Opencv3.4.3调用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;
#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 = "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()
{
	CV_TRACE_FUNCTION();
	String modelTxt = "bvlc_googlenet.prototxt";
	String modelBin = "bvlc_googlenet.caffemodel";
	String imageFile = "cup_1.jpg";
	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;
		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);
	}
	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 RGB-images
	Mat inputBlob = blobFromImage(img, 1, Size(224, 224),
		Scalar(104, 117, 123));   //Convert Mat to batch of images
	Mat prob;
	cv::TickMeter t;
	for (int i = 0; i < 10; i++)
	{
		CV_TRACE_REGION("forward");
		net.setInput(inputBlob, "data");        //set the network input
		t.start();
		prob = net.forward("prob");                          //compute output
		t.stop();
	}
	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;
	std::cout << "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " << t.getCounter() << " iterations)" << std::endl;
	system("pause");
	return 0;
} 

关于代码中所用到的文件:bvlc_googlenet.caffemodelbvlc_googlenet.prototxtsynset_words.txt

其中:bvlc_googlenet.caffemodel是模型文件,是GoogleNet在ImageNet上训练好的模型,bvlc_googlenet.prototxt是googleNet的结构文件,synset_words.txt是ImageNet上的类别信息。

实验结果

opencv3.4.3调用caffe分类模型

Best class: #812 'space shuttle'
Probability: 99.9828%
Time: 53.3045 ms (average from 10 iterations)

opencv3.4.3调用caffe分类模型

Best class: #504 'coffee mug'
Probability: 68.0434%
Time: 52.8983 ms (average from 10 iterations)