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++知识:
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 }
输出结果: