OpenCV3.3深度学习模块(DNN)应用-图像分类

DNN模块介绍

在OpenCV3.3版本发布中把DNN模块从扩展模块移到了OpenCV正式发布模块中,当前DNN模块最早来自Tiny-dnn,可以加载预先训练好的Caffe模型数据,OpenCV做了近一步扩展支持所有主流的深度学习框架训练生成与导出模型数据加载,常见的有如下:

  • Caffe
  • TensorFlow
  • Torch/PyTorch

OpenCV中DNN模块已经支持与测试过这些常见的网络模块

  • AlexNet
  • GoogLeNet v1 (also referred to as Inception-5h)
  • ResNet-34/50/...
  • SqueezeNet v1.1
  • VGG-based FCN (semantical segmentation network)
  • ENet (lightweight semantical segmentation network)
  • VGG-based SSD (object detection network)
  • MobileNet-based SSD (light-weight object detection network)

一:GoogleNet Caffe模型数据说明

OpenCV通过支持加载这些预先训练好的模型,实现图像分类、对象检测、语义分割、风格迁移等功能。支持Android/iOS等移动端平台开发。下面我们就以OpenCV3.3 使用Caffe的GoogleNet数据模型为例,实现对图像常见分类,OpenCV3.3的DNN模块使用的模型支持1000种常见图像分类、googlenet深度学习网络模型是2014图像分类比赛的冠军、首先是下载相关的数据模型文件

  • bvlc_googlenet.caffemodel
  • bvlc_googlenet.prototxt

其中prototxt是一个文本的JSON文件、一看就明白啦,另外一个文件二进制文件。文本文件只有你下载了OpenCV3.3解压缩之后就会在对应的目录发现。模型文件需要从以下地址下载即可: http://dl.caffe.berkeleyvision.org/bvlc_googlenet.caffemodel

二:编程实现

首先我们需要加载它官方指定的一张测试图像space_shuttle.jpg 是一张航天飞机的图片、OpenCV中加载图像的代码如下:

      Mat testImage = imread("D:/vcprojects/images/dnn/football.jpg");

    if (testImage.empty()) {

        printf("could not load image...\n");

        return -1;

    }

然后我们需要声明模型数据的路径与标记数据路径,加载创建网络模型,代码实现如下:

  // create googlenet with caffemodel text and bin

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

    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;

        return -1;

    }


    // 读取分类数据

    vector<String> labels = readClasslabels();


    //GoogLeNet accepts only 224x224 RGB-images

    Mat inputBlob = blobFromImage(testImage, 1, Size(224, 224), Scalar(104, 117, 123));

然后开始分类预测,根据prototxt中的开始的要求,我们需要输入迭代10次,输出预测分类的结果,代码实现如下:

// 支持1000个图像分类检测

    Mat prob;

    // 循环10+

    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;

    double classProb;


    minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber); // 可能性最大的一个

    int classIdx = classNumber.x; // 分类索引号

    printf("\n current image classification : %s, possible : %.2f \n", labels.at(classIdx).c_str(), classProb);


    putText(testImage, labels.at(classIdx), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);

    imshow("Image Category", testImage);

其中读取图像分类索引与文本描述的方法代码如下:

vector<String> readClasslabels() {

    std::vector<String> classNames;

    std::ifstream fp(labelFile);

    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;

}

三:效果显示

航天飞机测试图像

霸气威武的J10战斗机

玩具店

足球场上

四:完全的源代码

#include <opencv2/opencv.hpp>

#include <opencv2/dnn.hpp>

#include <iostream>


using namespace cv;

using namespace cv::dnn;

using namespace std;


String modelTxt = "D:/vcprojects/images/dnn/bvlc_googlenet.prototxt";

String modelBin = "D:/vcprojects/images/dnn/bvlc_googlenet.caffemodel";

String labelFile = "D:/vcprojects/images/dnn/synset_words.txt";


vector<String> readClasslabels();

int main(int argc, char** argv) {

    Mat testImage = imread("D:/vcprojects/images/dnn/football.jpg");

    if (testImage.empty()) {

        printf("could not load image...\n");

        return -1;

    }


    // create googlenet with caffemodel text and bin

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

    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;

        return -1;

    }


    // 读取分类数据

    vector<String> labels = readClasslabels();


    //GoogLeNet accepts only 224x224 RGB-images

    Mat inputBlob = blobFromImage(testImage, 1, Size(224, 224), Scalar(104, 117, 123)); 


    // 支持1000个图像分类检测

    Mat prob;

    // 循环10+

    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;

    double classProb;


    minMaxLoc(probMat, NULL, &classProb, NULL, &classNumber); // 可能性最大的一个

    int classIdx = classNumber.x; // 分类索引号

    printf("\n current image classification : %s, possible : %.2f \n", labels.at(classIdx).c_str(), classProb);


    putText(testImage, labels.at(classIdx), Point(20, 20), FONT_HERSHEY_SIMPLEX, 0.75, Scalar(0, 0, 255), 2, 8);

    imshow("Image Category", testImage);


    waitKey(0);

    return 0;

}


/* 读取图像的1000个分类标记文本数据 */

vector<String> readClasslabels() {

    std::vector<String> classNames;

    std::ifstream fp(labelFile);

    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;

}

原文发布于微信公众号 - OpenCV学堂(CVSCHOOL)

原文发表时间:2017-09-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏WD学习记录

21个项目玩转深度学习 学习笔记(2)

事实上,必须先读入数据后才能进行计算,假设读入用时0.1s,计算用时0.9秒,那么没过1s,GPU都会有0.1s无事可做,大大降低了运算的效率。

36210
来自专栏机器之心

教程 | TensorEditor :一个小白都能快速玩转的神经网络搭建工具

23960
来自专栏计算机视觉与深度学习基础

【深度学习】使用tensorflow实现VGG19网络

转载注明出处:http://blog.csdn.net/accepthjp/article/details/70170217 接上一篇AlexNet,本文讲...

87890
来自专栏CVer

利用OpenCV和Tesseract实现OCR和文本识别

本教程将介绍如何使用 OpenCV OCR。我们将使用 OpenCV、Python 和 Tesseract 执行文本检测和文本识别。

2.7K30
来自专栏贾志刚-OpenCV学堂

OpenCV中原始图像加载与保存压缩技巧

OpenCV中关于图像读写有两个函数imread与imwrite,imread加载的时候支持灰度图像、彩色图像、原始图像加载,默认情况下通过imread加载的图...

17910
来自专栏Jack-Cui

Caffe学习笔记(一):CIFRA-10在Caffe上进行训练学习

运行平台:Ubuntu14.04     安装完Caffe后,如何开始学习Caffe呢?一个不错的方法就是从Caffe自带的examples开始学起。在caff...

34270
来自专栏Petrichor的专栏

图像预处理: 规范化

23930
来自专栏PaddlePaddle

【进阶篇】命令行参数使用案例

编写|PaddlePaddle 排版|wangp 1 本地训练 本地训练的实验,诸如图像分类,自然语言处理等,通常都会使用下面这些命令行参数 paddle ...

33040
来自专栏人人都是极客

5.训练模型之利用训练的模型识别物体

接下来我们开始训练,这里要做三件事: 将训练数据上传到训练服务器,开始训练。 将训练过程可视化。 导出训练结果导出为可用作推导的模型文件。 配置 Pipelin...

43840
来自专栏mathor

“达观杯”文本智能处理挑战赛

 由于提供的数据集较大,一般运行时间再10到15分钟之间,基础电脑配置在4核8G的样子(越消耗内存在6.2G),因此,一般可能会遇到内存溢出的错误

40720

扫码关注云+社区

领取腾讯云代金券