OpenCV DNN模块官方教程(一)加载Caffe模型做图像分类

2020-09-23 14:34:34 浏览数 (1)

OpenCV DNN模块官方教程地址如下,可以查看各个对应的使用方法。

https://docs.opencv.org/4.4.0/d2/d58/tutorial_table_of_content_dnn.html

OpenCV DNN模块官方文档分上面七个部分讲解,后续将选取其中部分在Windows平台做讲解讲解演示。

第一个部分:加载Caffe框架的模型。在本实例中,您将学习使用Caffe Model Zoo中用GoogLeNet训练的用于图像分类的模型来进行图像分类。

去掉一些命令行的代码,将核心代码提取如下,并做简单介绍与演示:

代码语言:javascript复制
#include "pch.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>

using namespace std;
using namespace cv;
using namespace dnn;

std::vector<std::string> classes;

int main(int argc, char** argv)
{
  String model = "./bvlc_googlenet.caffemodel";
  String config = "./bvlc_googlenet.prototxt";
  String classesFile = "./classification_classes_ILSVRC2012.txt";
  int  backendId = 0;
  int  targetId = 0;

  CV_Assert(!model.empty());
  std::string file = classesFile;
  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);
  }

  Net net = readNet(model, config);

  static const std::string kWinName = "Deep learning image classification in OpenCV";
  namedWindow(kWinName, WINDOW_NORMAL);
  
  Mat img = imread("./test.jpg");
  Mat blob;
  float scale = 1.0;
  Scalar mean = Scalar(104, 117, 123);
  bool swapRB = true;
  blobFromImage(img, blob, scale, Size(224, 224), mean, swapRB, false);
  net.setInput(blob);
  Mat prob = net.forward();
  Point classIdPoint;
  double confidence;
  minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
  int classId = classIdPoint.x;
  // Put efficiency information.
  std::vector<double> layersTimes;
  double freq = getTickFrequency() / 1000;
  double t = net.getPerfProfile(layersTimes) / freq;
  std::string label = format("Inference time: %.2f ms", t);
  putText(img, label, Point(0, 20), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(255, 0, 0), 2);
  // Print predicted class.
  label = format("%s: %.4f", (classes.empty() ? format("Class #%d", classId).c_str() :
    classes[classId].c_str()),
    confidence);
  cout << "label: " << classes[classId].c_str() << endl;
  putText(img, label, Point(0, 45), FONT_HERSHEY_SIMPLEX, 0.7, Scalar(255, 0, 0), 2);
  imshow(kWinName, img);
  waitKey(0);
  return 0;
}

使用方法与说明:

(1) 首先,下载GoogleNet模型文件和ILSVRC2012类名称文件并放入工作目录

bvlc_googlenet.prototxt、bvlc_googlenet.caffemodel、

classification_classes_ILSVRC2012.txt

(2) 使用.prototxt和.caffemodel文件的路径读取和初始化网络

代码语言:javascript复制
 Net net = readNet(model, config, framework);

framework参数可以跳过,DNN模块可以根据model和config自动识别:

代码语言:javascript复制
Net net = readNet(model, config);

(3) 读取输入图像并将其转换为GoogleNet可接受的Blob

代码语言:javascript复制
blobFromImage(img, blob, scale, Size(224, 224), mean, swapRB, false);

(4) 将Blob传递到网络

代码语言:javascript复制
net.setInput(blob);

(5) 向前传递

代码语言:javascript复制
Mat prob = net.forward();

(6) 确定最佳类别

代码语言:javascript复制
Point classIdPoint;
double confidence;
minMaxLoc(prob.reshape(1, 1), 0, &confidence, 0, &classIdPoint);
int classId = classIdPoint.x;

(7) 设置对应参数和文件路径运行测试,如下是测试效果(运行时间 类别):

0 人点赞