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++知識:
https://www.cnblogs.com/Jack-Elvis/p/12171691.html
https://www.cnblogs.com/Jack-Elvis/p/12171939.html
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 }
輸出結果: