源代码如下:
#include
#include
#include
#include
using namespace cv;
using namespace cv::dnn;
#include
#include
#include
using namespace std;
/* Find best class for the blob (i.e. class with maximal probability) */
static void getMaxClass(const Mat&probBlob,int *classId, double *classProb)
{
Mat probMat = probBlob.reshape(1, 1); //reshapethe blob to 1x1000 matrix
Point classNumber;
minMaxLoc(probMat,NULL, classProb, NULL, &classNumber);
*classId = classNumber.x;
}
staticstd::vector<String> readClassNames(const char *filename= "F:/work/opencv/DNN/synset_words.txt")
{
std::vector<String> classNames;
std::ifstream fp(filename);
if (!fp.is_open())
{
std::cerr<< "File with classes labels not found: " << filename << std::endl;
exit(-1);
}
std::string name;
while (!fp.eof())
{
std::getline(fp,name);
if (name.length())
classNames.push_back(name.substr(name.find(' ') + 1));
}
fp.close();
return classNames;
}
intmain(int argc, char **argv)
{
CV_TRACE_FUNCTION();
String modelTxt = "F:/work/opencv/DNN/bvlc_googlenet.prototxt";
String modelBin = "F:/work/opencv/DNN/bvlc_googlenet.caffemodel";
//! [Read and initialize network]
Net net =dnn::readNetFromCaffe(modelTxt, modelBin);
//! [Read and initialize network]
waitKey(0);
//! [Check that network was read successfully]
if (net.empty())
{
std::cerr << "Can't load network by using thefollowing files: " << std::endl;
std::cerr<< "prototxt: " << modelTxt <<std::endl;
std::cerr<< "caffemodel: " << modelBin << std::endl;
std::cerr<< "bvlc_googlenet.caffemodel can be downloaded here:" <<std::endl;
std::cerr<< "http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel" <<std::endl;
exit(-1);
}
//! [Check that network was read successfully]
//! [Prepare blob]
Mat img = imread("F:/work/opencv/data/boat.jpg", WINDOW_AUTOSIZE);
waitKey(0);
if (img.empty())
{
std::cerr<< "Can't read image from the file: " <<std::endl;
exit(-1);
}
//GoogLeNet accepts only 224x224 RGB-images
Mat inputBlob =blobFromImage(img, 1, Size(224, 224),
Scalar(104, 117, 123)); //Convert Mat tobatch of images
//! [Prepare blob]
Mat prob;
cv::TickMeter t;
for (int i = 0; i < 10; i++)
{
CV_TRACE_REGION("forward");
//! [Set input blob]
net.setInput(inputBlob,"data"); //setthe network input
//! [Set input blob]
t.start();
//! [Make forward pass]
prob= net.forward("prob"); //computeoutput
//! [Make forward pass]
t.stop();
}
//! [Gather output]
int classId;
double classProb; // 分类索引号
getMaxClass(prob,&classId, &classProb);//find the best class
//! [Gather output]
//! [Print results]
std::vector<String> classNames =readClassNames();
putText(img,classNames.at(classId), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0,0, 255), 2, 8);
namedWindow("Image Category",WINDOW_NORMAL);
imshow("Image Category",img);
std::cout<< "Best class: #" << classId << " '" << classNames.at(classId) << "'" <<std::endl;
std::cout<< "Probability: " << classProb * 100 << "%" << std::endl;
//! [Print results]
std::cout<< "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " <<t.getCounter() << " iterations)" << std::endl;
waitKey(0);
return 0;
} //main
对程序的部分解读
1、 首先,下载GoogLeNet模块文件: bvlc_googlenet.prototxt 和 bvlc_googlenet.caffemodel;另外你还需要一个 ILSVRC2012 类名的文件:synset_words.txt。把这三个文件放在程序的工作目录里
2、 使用.prototxt和.caffemodel路径文件来读取并初始化网络
net= dnn::readNetFromCaffe(modelTxt,modelBin);
3、 检查网络是否读取成功
if (net.empty())
{
std::cerr <<"Can't load network by using the following files: " < std::cerr <<"prototxt: " < std::cerr <<"caffemodel: " << modelBin << std::endl; std::cerr <<"bvlc_googlenet.caffemodel can be downloaded here:" << std::endl; std::cerr <<"http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel"<< std::endl; exit(-1); } 4、 读取输入的图像,并转换成GoogleNet能接受的数据格式(blob)文件 Mat img = imread(imageFile); if (img.empty()) { std::cerr << "Can't read image from the file: "<< imageFile << std::endl; exit(-1); } //GoogLeNet accepts only 224x224 BGR-images Mat inputBlob = blobFromImage(img, 1.0f, Size(224, 224), Scalar(104,117, 123)); 首先,我们缩放图像,并且改变图像的通道顺序,现在呢图像实际上就是一个224x224x3的3维阵列;接下来,通过使用特定的函数 cv::dnn::blobFromImages再把这个图像转换成一个1x3x224x224形状的4维对象(blob)。 5、 把这个对象(blob)传给网络 net.setInput(inputBlob,"data"); //setthe network input 在bvlc_googlenet.prototxt文件里,网络输入对象称为数据,因此在opencv_dnn api接口里,这个标记过的对象也称为数据,不过其他标记过的对象称为层名或输出层名。 6、 做前向传输 prob = net.forward("prob"); 在前向传输过程中,每一个网络层的输出都被计算,但在本例程中我们仅从“prob”层输出 7、 决策判断出最佳分类 int classId; double classProb; getMaxClass(prob, &classId, &classProb);//find the bestclass 我们把”prob”层的输出放在probblob上,接着找出最大值元素的索引号,此索引号就是与识别到的图像类相关。 8、 在原图像上写上分类标识名 putText(img,classNames.at(classId), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0,255), 2, 8); namedWindow("Image Category",WINDOW_NORMAL); imshow("Image Category", img); 9、 打印结果 识别为独木舟,并在原图像上打印出来,其概率为52.6929% 若喜欢我的文章请关注下我的公众号