加載Caffe框架模型

2018-10-17 10:34 更新

介紹

在本教程中,您將學(xué)習(xí)如何使用OpenCv_dnn模塊進行圖像分類,方法是使用來自Caffe模型動物園的 GoogLeNet訓(xùn)練網(wǎng)絡(luò)。

我們將在下面的圖片中展示這個例子的結(jié)果。

加載Caffe框架模型

布蘭航天飛機

源代碼

我們將使用示例應(yīng)用程序的片段,可以在這里下載。

#include <opencv2/dnn.hpp>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui.hpp>
#include <opencv2/core/utils/trace.hpp>
using namespace cv;
using namespace cv::dnn;
#include <fstream>
#include <iostream>
#include <cstdlib>
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); //reshape the blob to 1x1000 matrix
    Point classNumber;
    minMaxLoc(probMat, NULL, classProb, NULL, &classNumber);
    *classId = classNumber.x;
}
static std::vector<String> readClassNames(const char *filename = "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;
}
int main(int argc, char **argv)
{
    CV_TRACE_FUNCTION();
    String modelTxt = "bvlc_googlenet.prototxt";
    String modelBin = "bvlc_googlenet.caffemodel";
    String imageFile = (argc > 1) ? argv[1] : "space_shuttle.jpg";
    Net net;
    try {
        net = dnn::readNetFromCaffe(modelTxt, modelBin);
    }
    catch (cv::Exception& e) {
        std::cerr << "Exception: " << e.what() << std::endl;
        if (net.empty())
        {
            std::cerr << "Can't load network by using the following 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);
        }
    }
    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), false);   //Convert Mat to batch of images
    Mat prob;
    cv::TickMeter t;
    for (int i = 0; i < 10; i++)
    {
        CV_TRACE_REGION("forward");
        net.setInput(inputBlob, "data");        //set the network input
        t.start();
        prob = net.forward("prob");                          //compute output
        t.stop();
    }
    int classId;
    double classProb;
    getMaxClass(prob, &classId, &classProb);//find the best class
    std::vector<String> classNames = readClassNames();
    std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
    std::cout << "Probability: " << classProb * 100 << "%" << std::endl;
    std::cout << "Time: " << (double)t.getTimeMilli() / t.getCounter() << " ms (average from " << t.getCounter() << " iterations)" << std::endl;
    return 0;
} //main

說明

        net = dnn :: readNetFromCaffe(modelTxt,modelBin);

  • 檢查網(wǎng)絡(luò)是否已成功讀取

        if (net.empty())
        {
            std::cerr << "Can't load network by using the following 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);
        }

  • 讀取輸入圖像并轉(zhuǎn)換為Blob,可由GoogleNet接受

    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), false);   //Convert Mat to batch of images

首先,我們調(diào)整圖像的大小并改變其頻道序列順序。

現(xiàn)在圖像實際上是一個具有224x224x3形狀的三維數(shù)組。

接下來,我們通過使用特殊的cv :: dnn :: blobFromImages構(gòu)造函數(shù)將圖像轉(zhuǎn)換為具有1x3x224x224形狀的4維blob(所謂批處理)。

  • 將blob傳遞到網(wǎng)絡(luò)

        net.setInput(inputBlob, "data");        //set the network input

在bvlc_googlenet.prototxt中,網(wǎng)絡(luò)輸入blob命名為“data”,因此這個blob在opencv_dnn API中標記為“.data”。

其他標記為“name_of_layer.name_of_layer_output”的blob。

  • Make forward pass

        prob = net.forward("prob");                          //compute output

在計算每個網(wǎng)絡(luò)層的正向傳輸輸出期間,但在本例中,我們僅需要“prob”層的輸出。

  • 確定最好的class

    int classId;
    double classProb;
    getMaxClass(prob, &classId, &classProb);//find the best class

我們把包含1000個ILSVRC2012圖像類別的概率的“prob”層的輸出放到probblob上。并在此找到具有最大值的元素的索引。該索引對應(yīng)于圖像的類。

  • 打印結(jié)果

    std::vector<String> classNames = readClassNames();
    std::cout << "Best class: #" << classId << " '" << classNames.at(classId) << "'" << std::endl;
    std::cout << "Probability: " << classProb * 100 << "%" << std::endl;

對于我們的形象我們得到:

Best class: #812 'space shuttle'

Probability: 99.6378%

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號