GoogleNet模型图像分类

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...
");
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...
"); //读取文件失败
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("
 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 }

输出结果:

原文地址:https://www.cnblogs.com/Jack-Elvis/p/12168927.html