1. 程式人生 > >【opencv3.4.1在DNN模組中使用googlenet模型】

【opencv3.4.1在DNN模組中使用googlenet模型】

    在OpenCV3.3版本釋出中把DNN模組從擴充套件模組移到了OpenCV正式釋出模組中,當前DNN模組最早來自Tiny-dnn,可以載入預先訓練好的Caffe模型資料,OpenCV做了近一步擴充套件支援所有主流的深度學習框架訓練生成與匯出模型資料載入。

按照官方介紹

支援以下框架

  • Caffe 1
  • TensorFlow
  • Torch/PyTorch

首先我們需要下載訓練好的googlenet權重模型bvlc_googlenet .caffemodel(二進位制檔案),模型下載地址為

然後匯入模型描述檔案,地址為C:\opencv\opencv\sources\samples\data\dnn


#include<opencv2\opencv.hpp>
#include<vector>
#include<string>

using namespace cv;
using namespace dnn;
using namespace std;

String model_file = "bvlc_googlenet.caffemodel";
String model_txtfile = "bvlc_googlenet.prototxt";
String labels_file = "synset_words.txt";

vector<String>readLabels();



int main(int arc, char** argv) {

	Mat src = imread("5.jpg");
	namedWindow("input", CV_WINDOW_AUTOSIZE);
	imshow("input", src);

	//讀取模型的類別(文字)
	vector<String> labels = readLabels();


	//讀取google_net的模型和描述檔案
	Net net = readNetFromCaffe(model_txtfile, model_file);
	if (net.empty()) {

		printf("read caffee model data failure\n");

		return -1;

	}

	//將影象轉為google_net網路輸入的物件,由描述檔案可知,影象尺寸統一為224*224
	Mat inputBlob = blobFromImage(src, 1.0, Size(224, 224), Scalar(104, 117, 123));
	//進行前向傳播,由描述檔案可知,第一層用了10個卷積層,提取影象10種不同的特徵
	Mat prob;
        //迴圈10次為了更精確
	for (int i = 0; i < 10; i++) {
		net.setInput(inputBlob, "data");
		prob = net.forward("prob");//最後一層的輸出為“prob”
	}



	//輸出

	//printf("m = %d,n = %d", prob.rows, prob.cols);//得到的概率值為1行1000列的

	Point classLoc;
	double classProb;
	minMaxLoc(prob, NULL, &classProb, NULL, &classLoc); // 找出 probMat 中最大可能性的分類
	printf("current image classification: %s,probablity %f\n", labels.at(classLoc.x).c_str(), classProb);
	putText(src, labels.at(classLoc.x), Point(20, 20), FONT_HERSHEY_COMPLEX, 1.0, Scalar(0, 0, 255), 2);
	imshow("output", src);
	waitKey(0);
	return 0;

}



//讀取模型的類別(文字)

vector<String>readLabels() {
	vector<String>classNames;
	ifstream fp(labels_file);//開啟檔案
	if (!fp.is_open()) {//檔案沒開啟
		printf("could not open the file ");
		exit(-1);
	}

	string name;

	while (!fp.eof()) {//檔案沒讀到結尾
		getline(fp, name);//得到每一行,放到name中
		if (name.length()) {//非空行
			classNames.push_back(name.substr(name.find(' ') + 1));//
		}
	}

	fp.close();
	return classNames;

}

輸出: