OpenCV 中使用Caffe中训练好的model

在OpenCV中使用Caffe中训练好的model

以 LeNet 为例子

第一步: 改写deploy文件

按下面的步骤修改文件 lenet_train_test.prototxt


(1) 去掉数据输入层,即top 为 “data” 的layers 去掉

      即将下面的内容删掉     

layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TRAIN
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_train_lmdb"
    batch_size: 64
    backend: LMDB
  }
}
layer {
  name: "mnist"
  type: "Data"
  top: "data"
  top: "label"
  include {
    phase: TEST
  }
  transform_param {
    scale: 0.00390625
  }
  data_param {
    source: "examples/mnist/mnist_test_lmdb"
    batch_size: 100
    backend: LMDB
  }
}

(2) 重新建立输入

     即添加下面的内容

input: "data"
input_shape {
  dim: 1   # batchsize
  dim: 1   # number of channels 
  dim: 28  # width
  dim: 28  # height
}


(3) 去掉输出层,即将bottom 为 “label” 的layers 去掉

     即将下面的内容删掉

     

layer {
  name: "accuracy"
  type: "Accuracy"
  bottom: "ip2"
  bottom: "label"
  top: "accuracy"
  include {
    phase: TEST
  }
}
layer {
  name: "loss"
  type: "SoftmaxWithLoss"
  bottom: "ip2"
  bottom: "label"
  top: "loss"
}


(4) 重新建立输出

   即添加下面的内容

layer {
  name: "prob"
  type: "Softmax"
  bottom: "ip2"
  top: "prob"
}

修改完后保存到文件中(mnist_deploy.prototxt,内容如下

name: "LeNet"
input: "data"
input_shape {
  dim: 1   # batchsize
  dim: 1   # number of channels
  dim: 28  # width
  dim: 28  # height
}
layer {
  name: "conv1"
  type: "Convolution"
  bottom: "data"
  top: "conv1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 20
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool1"
  type: "Pooling"
  bottom: "conv1"
  top: "pool1"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "conv2"
  type: "Convolution"
  bottom: "pool1"
  top: "conv2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  convolution_param {
    num_output: 50
    kernel_size: 5
    stride: 1
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "pool2"
  type: "Pooling"
  bottom: "conv2"
  top: "pool2"
  pooling_param {
    pool: MAX
    kernel_size: 2
    stride: 2
  }
}
layer {
  name: "ip1"
  type: "InnerProduct"
  bottom: "pool2"
  top: "ip1"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 500
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "relu1"
  type: "ReLU"
  bottom: "ip1"
  top: "ip1"
}
layer {
  name: "ip2"
  type: "InnerProduct"
  bottom: "ip1"
  top: "ip2"
  param {
    lr_mult: 1
  }
  param {
    lr_mult: 2
  }
  inner_product_param {
    num_output: 10
    weight_filler {
      type: "xavier"
    }
    bias_filler {
      type: "constant"
    }
  }
}
layer {
  name: "prob"
  type: "Softmax"
  bottom: "ip2"
  top: "prob"
}


第二步:使用cv::dnn 里的API加载model, 输入图片,进行测试

代码如下:

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>

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

/* 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);
    Point classNumber;
    minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
    *classId = classNumber.x;
}

int main(int argc, char *argv[])
{
    string modelTxt = "../mnist_deploy.prototxt";
    string modelBin = "../lenet_iter_10000.caffemodel";
    string imgFileName = argc > 1 ? argv[1] : "../4.jpg";
    //read image
    Mat imgSrc = imread(imgFileName);
    if(imgSrc.empty()){
        cout << "Failed to read image " << imgFileName << endl;
        exit(-1);
    }
    Mat img;
    cvtColor(imgSrc, img, COLOR_BGR2GRAY);
    //LeNet accepts 28*28 gray image
    resize(img, img , Size(28, 28)); 
    //in the file "lenet_train_test.prototxt", in the Data input layer, we can see
    //  transform_param {
    //    scale: 0.00390625
    //  }
    //which means the input data need to be normalized before feed the data into the net
    // 0.00390625 = 1/255 after this operation, the value of the image pixel will be transferred to be one value between 0 and 1
    img /=255;

    //transfer image(1*28*28) to blob data with 4 dimensions(1*1*28*28) 
    Mat inputBlob = dnn::blobFromImage(img); 
    dnn::Net net; 
    try{ 
        net = dnn::readNetFromCaffe(modelTxt, modelBin); 
    }catch(cv::Exception &ee){ 
      cerr << "Exception: " << ee.what() << endl; 
      if(net.empty()){ 
         cout << "Can't load the network by using the flowing files:" << endl; 
         cout << "modelTxt: " << modelTxt << endl; 
         cout << "modelBin: " << modelBin << endl; exit(-1); 
      }
    } 
    Mat pred; 
    net.setInput(inputBlob, "data");//set the network input, "data" is the name of the input layer 
    pred = net.forward("prob");//compute output, "prob" is the name of the output layer 
    cout << pred << endl; int classId; double classProb; getMaxClass(pred, &classId, &classProb); 
    cout << "Best Class: " << classId << endl;
    cout << "Probability: " << classProb*100 << "%" << endl;
}


编译代码并运行,测试结果如下:


下面的代码是测试多张图片

#include <iostream>
#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
using namespace std;
using namespace cv;
using namespace cv::dnn;
/* 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);
    Point classNumber;
    minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
    *classId = classNumber.x;
}
int main(int argc, char *argv[])
{
    string modelTxt = "../mnist_deploy.prototxt";
    string modelBin = "../lenet_iter_10000.caffemodel";
    if(argc < 2){
        cout << "Please input image file name!!!" << endl;
        return -1;
    }

    Mat inputBlob;
    vector<Mat> imgVec;
    for(int i = 1;  i < argc; i++){
        string imgFileName = argv[i];
        Mat imgSrc = imread(imgFileName);
        if(imgSrc.empty()){
            cout << "Failed to read image " << imgFileName << endl;
            exit(-1);
        }

        Mat img;
        cvtColor(imgSrc, img, COLOR_BGR2GRAY);
        resize(img, img , Size(28, 28));
        img /= 255; 
        imgVec.push_back(img);
    }
    inputBlob = dnn::blobFromImages(imgVec);
 
    dnn::Net net;
    try{
        net = dnn::readNetFromCaffe(modelTxt, modelBin);
    }catch(cv::Exception &ee){
        cerr << "" << ee.what() << endl;
        if(net.empty()){
            cout << "Can't load the network by using the flowing files:" << endl;
            cout << "modelTxt: " << modelTxt << endl;
            cout << "modelBin: " << modelBin << endl;
            exit(-1);
        }
    }

    Mat pred;
    net.setInput(inputBlob, "data");
    pred = net.forward("prob");
    cout << endl;
    cout << pred << endl;
    cout << endl;
    for(int i = 0; i < imgVec.size(); i++){
        int classId;
        double classProb;
        getMaxClass(pred.row(i), &classId, &classProb);
        cout << "The class id of image " << argv[i+1] << " is: " << classId << endl;
        cout << "The probability is: " << classProb*100 << "%" << endl;
    }
    cout << endl;

}


测试结果如下:


测试用到的几张图片:



注:本文中的代码所调用的API是基于OpenCV 3.3.0版本的






©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页