Googlenet模型進行圖像分類

有三個檔案需要下載下傳:
第一個是caffe模型,第二個是整個網絡的描述檔案,第三個是1000種分類對應的名稱表
主要的API有以下:
1.blobFromImage函數;
2.reshape()方法;
一、作用:常使用在對矩陣的處理上
二、函數特點:reshape函數是針對對目标函數取資料用于重新布局時,是按照列的方式來擷取資料的
三、幾種常見使用方式:
方式一:arr.reshape((m,n)) 意思是把arr矩陣變成一個新的m行n列的矩陣
方式二:arr.reshape(-1,1) -1表示按照行的方式的擷取,結果形成一列
方式三:arr.reshape(m,n,q) 得到多元數組
3.minMaxLoc函數;
其它相關C++知識:
1.ofstream和ifstream讀檔案用法介紹:
https://www.cnblogs.com/Jack-Elvis/p/12171691.html
2.getline(cin, name) 逐行複制函數:
https://www.cnblogs.com/Jack-Elvis/p/12171939.html
3.push方法與push_back方法:
https://www.cnblogs.com/Jack-Elvis/p/12172511.html
代碼如下:
1 #include <opencv2/opencv.hpp>
2 #include <opencv2/dnn.hpp>
3 #include <iostream>
4
5 using namespace cv;
6 using namespace cv::dnn;
7 using namespace std;
8 //導入卷積網路dnn的頭檔案、建立dnn工作空間
9 String model_bin_file = "L:/googlenet/bvlc_googlenet.caffemodel";
10 String model_txt_file = "L:/googlenet/bvlc_googlenet.prototxt";
11 String labels_txt_file = "L:/googlenet/synset_words.txt";
12 //讀取googlenet的三個檔案,caffe模型二進制,網絡描述文本檔案,1000種分類表格的名稱檔案
13
14 vector<String> readLabels(); //調用readLabels()
15
16 int main(int argc, char** argv) {
17 Mat src = imread("L:dog.jpg");
18 if (src.empty()) {
19 printf("could not load image...\n");
20 return -1;
21 }
22 namedWindow("input image", CV_WINDOW_AUTOSIZE);
23 imshow("input image", src);
24 vector<String> labels = readLabels();
25 Net net = readNetFromCaffe(model_txt_file, model_bin_file);
26 //使用readNetFromCaffe方法讀取前面兩個模型檔案
27 if (net.empty()) {
28 printf("read caffe model data failure...\n"); //讀取檔案失敗
29 return -1;
30 }
31 Mat inputBlob = blobFromImage(src, 1.0, Size(224, 224), Scalar(104, 117, 123));
32 //blobFromImage函數:1.輸入圖像 2.縮放尺度 3.圖像大小 4.輸入圖的像素減去各通道的均值
33
34 Mat prob; //預測的準确率
35 for (int i = 0; i < 10; i++) {
36 net.setInput(inputBlob, "data");
37 //将inputBlob内容輸入到網絡的第一層的第一個input為data (與網絡的描述檔案對應)
38 prob = net.forward("prob"); //将通過描述檔案計算後的prob值賦給變量prob
39 }
40 Mat probMat = prob.reshape(1, 1);
41 //reshape()方法将矩陣prob變成一行多列(這裡是1000列)的矩陣probMat
42 Point classNumber;
43 double classProb;
44 minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber);
45 //minMaxLoc函數為尋找矩陣最大最小值及位置
46 // 參數: 1.帶尋找矩陣 2.最小值 3.最大值 4.最小值位置 5.最大值位置
47 int classidx = classNumber.x; //找出最大值的行數
48 printf("\n current image classification : %s, possible : %.2f", labels.at(classidx).c_str(), classProb);
49 // labels.at(classidx) 是最大行對應的labels标簽 .c_str()是将内容轉換為字元串型
50 putText(src, labels.at(classidx), Point(20, 20), FONT_HERSHEY_SIMPLEX, 1.0, Scalar(0, 0, 255), 2, 8);
51 imshow("Image Classification", src);
52
53 waitKey(0);
54 return 0;
55 }
56
57 vector<String> readLabels() {
58 vector<String> classNames; //定義分類名稱變量(labels_name)
59 ifstream fp(labels_txt_file); //檔案輸出流的方式讀取label words
60 if (!fp.is_open()) { //檔案不能打開
61 printf("could not open the file");
62 exit(-1); //非正常退出,傳回值為-1
63 }
64 string name;
65 while (!fp.eof()) { //如果沒有讀到檔案尾部
66 getline(fp, name); //getline函數逐行複制給name(空格不作為分隔符)
67 if (name.length()) { //如果name.length有值
68 classNames.push_back(name.substr(name.find(\' \') + 1));
69 //name.find()方法找到name中所有空格+1的位置
70 //name.substr()方法截取name中空格+1位置後面的字元串
71 //classNames.push_back()方法将所有行截取的字元以堆棧壓入className
72 }
73 }
74 fp.close(); //關閉檔案
75 return classNames; //傳回值為className
76 }
輸出結果: