OpenCV3.3 深度学习模块-对象检测演示

OpenCV3.3 深度学习模块-对象检测演示

一:概述

OpenCV3.3 DNN模块功能十分强大,可以基于已经训练好的模型数据,实现对图像的分类与图像中的对象检测在图像与实时视频中,上次发的一篇文章介绍了DNN模块实现图像分类,这篇文章介绍DNN模块实现对图像中对象检测与标记。当前比较流行基于卷积神经网络/深度学习的对象检测方法主要有以下三种:

  • Faster R-CNNs

  • You Only Look Once(YOLO)

  • Single Shot Detectors(SSD)

其中第一种Faster R-CNNs对初学深度来说是很难理解与训练的网络模型,而且该方法虽然号称是Fast,其实在实时对象检测时候,比后面两中方法要慢很多,每秒帧率非常低。最快的是YOLO,据说帧率可以达到40~90 FPS、另外SSD实时帧率号称20~40FPS,我在我的i5的笔记本上测试了SSD感觉只有10FPS左右,基本超过视频最低的5FPS的最低值。可能是我的笔记本比较旧。

二:模型数据

本文的演示是基于SSD模块数据完成,OpenCV 3.3 使用的SSD模型数据有两种,一种是支持100个分类对象检测功能的,主要是用于对图像检测;另外一种是可以在移动端时候、可以支持实时视频对象检测的,支持20个分类对象检测。本人对这两种方式都下载了数据模型做了测试。发现使用mobilenet版本响应都在毫秒基本,速度飞快,另外一种SSD方式,基本上针对图像,都是1~2秒才出结果。数据模型的下载可以从下面的链接:

https://github.com/weiliu89/caffe/tree/ssd#models

三:演示效果

针对图像的SSD对象检测

针对视频实时对象检测mobilenet SSD对象检测结果,我用了OpenCV自带的视频为例,运行截图:

四:演示代码

相关注释已经写在代码里面,不在多废话、解释!代码即文档!

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

  2.    Mat frame = imread("D:/vcprojects/images/dnn/004545.jpg");

  3.    // Mat frame = imread("D:/vcprojects/images/paiqiu.png");

  4.    // Mat frame = imread("D:/vcprojects/images/dnn/000456.jpg");

  5.    // Mat frame = imread("D:/vcprojects/images/ssd.jpg");

  6.    if (frame.empty()) {

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

  8.        return -1;

  9.    }

  10.    // 读取分类文本标记

  11.    Ptr<dnn::Importer> importer;

  12.    vector<String> text_labels = readClasslabels();

  13.    // Import Caffe SSD model

  14.    try

  15.    {

  16.        importer = dnn::createCaffeImporter(modelConfiguration, modelBinary);

  17.    }

  18.    catch (const cv::Exception &err)

  19.    {

  20.        cerr << err.msg << endl;

  21.    }

  22.    // 初始化网络

  23.    dnn::Net net;

  24.    importer->populateNet(net);

  25.    importer.release();

  26.    // 准备输入数据,

  27.    Mat preprocessedFrame = preprocess(frame); // 300x300 resize substract means

  28.    Mat inputBlob = blobFromImage(preprocessedFrame);

  29.    // 检测

  30.    net.setInput(inputBlob, "data");  // 输入层 data

  31.    Mat detection = net.forward("detection_out");  // 输出到最后一层

  32.    Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

  33.    // 根据置信阈值设置,绘制对象矩形

  34.    float confidenceThreshold = 0.1;

  35.    for (int i = 0; i < detectionMat.rows; i++)

  36.    {

  37.        float confidence = detectionMat.at<float>(i, 2);

  38.        // printf("current confidence %.2f \n", confidence);

  39.        if (confidence > confidenceThreshold)

  40.        {

  41.            size_t objectClass = (size_t)(detectionMat.at<float>(i, 1));

  42.            float xLeftBottom = detectionMat.at<float>(i, 3) * frame.cols;

  43.            float yLeftBottom = detectionMat.at<float>(i, 4) * frame.rows;

  44.            float xRightTop = detectionMat.at<float>(i, 5) * frame.cols;

  45.            float yRightTop = detectionMat.at<float>(i, 6) * frame.rows;

  46.            // 得到分类ID与置信值

  47.            std::cout << "Class: " << objectClass << std::endl;

  48.            std::cout << "Confidence: " << confidence << std::endl;

  49.            std::cout << " " << xLeftBottom

  50.                << " " << yLeftBottom

  51.                << " " << xRightTop

  52.                << " " << yRightTop << std::endl;

  53.            Rect object((int)xLeftBottom, (int)yLeftBottom,

  54.                (int)(xRightTop - xLeftBottom),

  55.                (int)(yRightTop - yLeftBottom));

  56.            // 绘制矩形与分类文本

  57.            rectangle(frame, object, Scalar(0, 0, 255), 2, 8, 0);

  58.            putText(frame, format("%s", text_labels[objectClass].c_str()), Point((int)xLeftBottom, (int)yLeftBottom), FONT_HERSHEY_SIMPLEX, 0.65, Scalar(0, 255, 0), 2, 8);

  59.        }

  60.    }

  61.    imshow("detections", frame);

  62.    waitKey(0);

  63.    return 0;

  64. }

其中读取分类标记文档代码如下:

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

  2. vector<String> readClasslabels() {

  3.    std::vector<String> classNames;

  4.    std::ifstream fp(labelFile);

  5.    if (!fp.is_open())

  6.    {

  7.        std::cerr << "File with classes labels not found: " << labelFile << std::endl;

  8.        exit(-1);

  9.    }

  10.    std::string name;

  11.    while (!fp.eof())

  12.    {

  13.        std::getline(fp, name);

  14.        if (name.length() && (name.find("display_name:") == 0)) {

  15.            string temp = name.substr(15);

  16.            temp.replace(temp.end()-1, temp.end(), "");

  17.            printf("current row content %s\n", temp.c_str());

  18.            classNames.push_back(temp);

  19.        }

  20.    }

  21.    fp.close();

  22.    return classNames;

  23. }


求木之长者,必固其根本;

欲流之远者,必浚其泉源!


关注【OpenCV学堂】

长按或者扫码下面二维码即可关注

+OpenCV学习群 376281510

进群暗号:OpenCV

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值