超详细!使用OpenCV深度学习模块在图像分类下的应用实践
加入极市专业CV交流群,与 10000+来自港科大、北大、清华、中科院、CMU、腾讯、百度 等名校名企视觉开发者互动交流!
同时提供每月大咖直播分享、真实项目需求对接、干货资讯汇总,行业技术交流。关注 极市平台 公众号 ,回复 加群,立刻申请入群~
极市导读:本文来自6月份出版的新书《OpenCV深度学习应用与性能优化实践》,由Intel与阿里巴巴高级图形图像专家联合撰写,系统地介绍了OpenCV DNN 推理模块原理和实践。极市为大家争取到5本赠书福利,详见文末。
#include <fstream>
#include <sstream>
#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include "common.hpp"
9-2 命令行参数定义
std::string keys=
"{ help h | | Print help message. }"
"{ @alias | | An alias name of model to extract preprocessing parameters from models.yml file. }"
"{ zoo | models.yml | An optional path to file with preprocessing parameters }"
"{ input i | | Path to input image or video file. Skip this argument to capture frames from a camera.}"
"{ framework f | | Optional name of an origin framework of the model. Detect it automatically if it does not set. }"
"{ classes | Optional path to a text file with names of classes. }"
"{ backend | 0 | Choose one of computation backends: "
"0: automatically (by default), "
"1: Halide language (http://halide-lang.org/), "
"2: Intel's Deep Learning Inference Engine (https://software.intel.com/openvino-toolkit), "
"3: OpenCV implementation }"
"{ target | 0 | Choose one of target computation devices: "
"0: CPU target (by default), "
"1: OpenCL, "
"2: OpenCL fp16 (half-float precision), "
"3: VPU }";
9-3 声明命名空间及定义全局变量
using namespace cv;
using namespace dnn;
std::vector<std::string> classes;
9-4 主函数(解析命令行参数)
int main(int argc, char** argv)
{
CommandLineParser parser(argc, argv, keys);
const std::string modelName=parser.get<String>("@alias");
const std::string zooFile=parser.get<String>("zoo");
keys +=genPreprocArguments(modelName, zooFile);
parser=CommandLineParser(argc, argv, keys);
parser.about("Use this script to run classification deep learning networks using OpenCV.");
if (argc==1 || parser.has("help"))
{
parser.printMessage();
return 0;
}
float scale=parser.get<float>("scale");
Scalar mean=parser.get<Scalar>("mean");
bool swapRB=parser.get<bool>("rgb");
int inpWidth=parser.get<int>("width");
int inpHeight=parser.get<int>("height");
String model=findFile(parser.get<String>("model"));
String config=findFile(parser.get<String>("config"));
String framework=parser.get<String>("framework");
int backendId=parser.get<int>("backend");
int targetId=parser.get<int>("target");
9-5 主函数(类别文件解析)
if (parser.has("classes"))
{
std::string file=parser.get<String>("classes");
std::ifstream ifs(file.c_str());
if (!ifs.is_open())
CV_Error(Error::StsError, "File " + file + " not found");
std::string line;
while (std::getline(ifs, line))
{
classes.push_back(line);
}
}
9-6 主函数(异常情况检查)
if (!parser.check())
{
parser.printErrors();
return 1;
}
CV_Assert(!model.empty());
9-7 主函数(初始化网络并创建显示窗口)
Net net=readNet(model, config, framework);
net.setPreferableBackend(backendId);
net.setPreferableTarget(targetId);
static const std::string kWinName="Deep learning image classification in OpenCV";
namedWindow(kWinName, WINDOW_NORMAL);
9-8 主函数(创建图像输入对象)
VideoCapture cap;
if (parser.has("input"))
cap.open(parser.get<String>("input"));
else
cap.open(0);
9-9 图像处理循环(读取一帧图像)
Mat frame, blob;
while (waitKey(1) < 0)
{
cap >> frame;
if (frame.empty())
{
waitKey();
break;
}
9-10 图像处理循环(设置网络输入)
blobFromImage(frame, blob, scale, Size(inpWidth, inpHeight),
mean, swapRB, false);
net.setInput(blob);
Mat prob=net.forward();
9-11 图像处理循环(解析网络推理输出)
Point classIdPoint;
double confidence;
// 找到概率值最大的类别id,该类别为图像所属分类
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
int classId=classIdPoint.x;
9-12 图像处理循环(可视化推理结果)
// 获取网络推理运算耗时,并叠加到原始图像上
std::vector<double> layersTimes;
double freq=getTickFrequency() / 1000;
double t=net.getPerfProfile(layersTimes) / freq;
std::string label=format("Inference time: %.2f ms", t);
putText(frame, label, Point(0, 15), FONT_HERSHEY_SIMPLEX,
0.5, Scalar(0, 255, 0));
// 将图像类别标签和概率值叠加到原始图像上
label=format("%s: %.4f", (classes.empty() ?
format("Class #%d", classId).c_str() :
classes[classId].c_str()),confidence);
putText(frame, label, Point(0, 40), FONT_HERSHEY_SIMPLEX,
0.5, Scalar(0, 255, 0));
// 显示图像
imshow(kWinName, frame);
}
// 循环结束,退出主函数
return 0;
}
赞 (0)