废话不多说,直接上代码,干货满满!!!
opencv中的dnn模块是很好用的!!!
#include "opencv2/opencv.hpp"
#include "opencv2/dnn.hpp"
#include <iostream>
#include <fstream>
/*
深度网络(Net)是由许多互相连接的层(layers)组合成的组合模型,Caffe定义的网络模型就是这样逐层(layers)连接。
Net包含了整个自顶向下的网络,网络由各个Layer组合而成;
Layer指处理数据的单层运算算子(比如卷积运算、pooling运算等);
Blob是网络运行时数据存储、传递和操作的接口;
*/
using namespace cv;
using namespace cv::dnn;//opencv dnn 模块
using namespace std;
String modelTxt = "bvlc_googlenet.prototxt";//模型参数
String modelBin = "bvlc_googlenet.caffemodel";//模型配置文件即模型框架
String labelFile = "synset_words.txt";//imageNet标签文件
vector<String> readLabels();
int main(int argc, char** argv) {
Mat testImage = imread("spacetrain.jpg");//读入分类图片,(可改写成capture cap即视频)
if (testImage.empty())
{
cout << "could not load image..." << endl;
return -1;
}
//使用caffe model创建Net
Net net = dnn::readNetFromCaffe(modelTxt, modelBin);
//dnn.readNetFromCaffe(prototxt, model) 用于进行SSD网络的caffe框架的加载
//参数说明:prototxt表示caffe网络的结构文本,model表示已经训练好的参数结果
//详情查看博客https://blog.csdn.net/weixin_33850015/article/details/93458287
if (net.empty())
{
std::cerr << "Can't load network by using the following files: " << std::endl;//写到cerr的数据是不缓冲的。Cerr通常用于输出错误信息与其他不属于正常逻辑的输出内容
std::cerr << "prototxt: " << modelTxt << std::endl;
std::cerr << "caffemodel: " << modelBin << std::endl;
return -1;
}
// 读取分类数据
vector<String> labels = readLabels();
//GoogLeNet 接受224x224 RGB图像
Mat inputBlob = blobFromImage(testImage, 1, Size(224, 224), Scalar(104, 117, 123), false, true);
//blobFromImage()函数,在进行深度学习或者图片分类时,blobFromImage主要是用来对图片进行预处理。包含两个主要过程:整体像素值减去平均值(mean)通过缩放系数(scalefactor)对图片像素值进行缩放
//参数说明:
//输入神经网络进行处理或者分类的图片
//图片减去平均值之后,还可以对剩下的像素值进行一定的尺度缩放,它的默认值是1,如果希望减去平均像素之后的值,全部缩小一半,那么可以将scalefactor设为1/2。
//神经网络在训练的时候要求输入的图片尺寸
//OpenCV中认为我们的图片通道顺序是BGR,但是我平均值假设的顺序是RGB,所以如果需要交换R和G,那么就要使swapRB=true
//详情查看博客https://blog.csdn.net/u011341856/article/details/100041050
Mat prob;
for (int i = 0; i < 10; i++)
{
// 输入
net.setInput(inputBlob, "data");
// 分类预测
prob = net.forward("prob");
}
// 读取分类索引,最大与最小值
Mat probMat = prob.reshape(1, 1); //reshape the blob to 1x1000 matrix // 1000个分类
Point classNumber; //一个点类 Point
double classProb;
minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber); // 可能性最大的一个
int classIdx = classNumber.x; // 分类索引号
cout << "\n current image classification : %s, possible : %.2f \n", labels.at(classIdx).c_str(), classProb;
//c_str()函数返回一个指向正规C字符串的指针, 内容与本string串相同
//c_str():生成一个const char*指针,指向以空字符终止的数组。
putText(testImage, labels.at(classIdx), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 99, 123), 2, 8);
//putText()往指定位置进行文本写入
//需要写字的原图像
//需要写的内容,string类型的
//需要写的内容的左下角的坐标
//字体大小
//颜色
//字体的厚度
//默认8
imshow("Image Category", testImage);
waitKey(0);
return 0;
}
//读取图像的1000个分类标记文本数据
vector<String> readLabels()
{
std::vector<String> classNames;
std::ifstream fp(labelFile);//fp指向文件synset_words.txt
if (!fp.is_open())
{
std::cerr << "File with classes labels not found: " << labelFile << 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;
}
识别效果如图:
代码中使用的3个文件:
String modelTxt = “bvlc_googlenet.prototxt”;//模型参数
String modelBin = “bvlc_googlenet.caffemodel”;//模型配置文件即模型框架
String labelFile = “synset_words.txt”;//imageNet标签文件
请加QQ群 109530331,问我要,嘻嘻嘻嘻!!!!!!!!!!
版权声明:本文为qq_43475606原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。