OpenCV-DNN使用SSD网络目标检测

原创 2018年04月17日 19:26:57

开发环境

    VS2013 + OpenCV3.4.1 + Qt5.8.0

实验准备

    VGG_VOC0712_SSD_300x300_iter_120000.caffemodel

    deploy.prototxt

    以上数据可以由这里下载得到(或者直接下载本工程),使用的是基于Caffe+VOC0712数据集训练出来的caffemodel。

主要代码

读取网络

string modelTxt = "caffe_ssd_300x300/deploy.prototxt";
string modelBin = "caffe_ssd_300x300/VGG_VOC0712_SSD_300x300_iter_120000.caffemodel";
try{

	net = dnn::readNetFromCaffe(modelTxt, modelBin);
}
catch (cv::Exception &ee){

	QMessageBox::warning(this, "Exception", ee.what());
	if (net.empty()){

		QMessageBox::warning(this, "Exception", "Can't load the network by using the flowing files.");
		return;
	}
}

前向识别

Mat frame;
image.copyTo(frame);
if (frame.empty()){

	QMessageBox::warning(this, "Warning", "image is empty, please check!");
	return;
}
if (frame.channels() == 4) cvtColor(frame, frame, COLOR_BGRA2BGR);
	
double ttt = (double)cvGetTickCount();

Mat inputBlob = blobFromImage(frame, 1.0f, Size(300, 300), Scalar(104, 117, 123), false, false); //Convert Mat to batch of images
net.setInput(inputBlob, "data");						//set the network input
Mat detection = net.forward("detection_out");			//compute output

ostringstream ss;
vector<double> layersTimings;
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());

ttt = (double)cvGetTickCount() - ttt;
ui.labelTime->setText(toChinese("识别时间:") + QString::number(ttt / (cvGetTickFrequency() * 1000000)) + toChinese("秒"));

float confidenceThreshold = ui.dsbConfidence->value();
for (int i = 0; i < detectionMat.rows; i++){

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

	if (confidence > confidenceThreshold){

		size_t objectClass = (size_t)(detectionMat.at<float>(i, 1));
		int xLeftBottom = static_cast<int>(detectionMat.at<float>(i, 3) * frame.cols);
		int yLeftBottom = static_cast<int>(detectionMat.at<float>(i, 4) * frame.rows);
		int xRightTop	= static_cast<int>(detectionMat.at<float>(i, 5) * frame.cols);
		int yRightTop	= static_cast<int>(detectionMat.at<float>(i, 6) * frame.rows);
		ss.str("");
		ss << confidence;
		String conf(ss.str());
		Rect object(xLeftBottom, yLeftBottom, xRightTop - xLeftBottom, yRightTop - yLeftBottom);
		rectangle(frame, object, Scalar(0, 0, 255));
		//String label = String(classNames[objectClass]) + ": " + conf;
		String label = String(classNamesZH[objectClass]) + ": " + conf;
		
		int baseLine = 0;
		Size labelSize = getTextSize(label, FONT_HERSHEY_SIMPLEX, 0.48, 1, &baseLine);
		rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom + labelSize.height / 2 - 4),
			Size(labelSize.width, labelSize.height + baseLine)),
			Scalar(255, 255, 255), FILLED);

		//putText(frame, label, Point(xLeftBottom, yLeftBottom), FONT_HERSHEY_SIMPLEX, 0.48, Scalar(0, 0, 0));
		putTextZH(frame, label.c_str(), Point(xLeftBottom, yLeftBottom), Scalar(0, 0, 255), 14, "Arial");
	}
}

Mat detectionMat是输入图像后经过网络前向传播后的输出7*10的结果矩阵,其定义如下图所示:


目标为20分类,定义如下:

const char* classNames[] = { "background",
"aeroplane", "bicycle", "bird", "boat",
"bottle", "bus", "car", "cat", "chair",
"cow", "diningtable", "dog", "horse",
"motorbike", "person", "pottedplant",
"sheep", "sofa", "train", "tvmonitor" };

const char* classNamesZH[] = { 
"背景","飞机", "自行车", "鸟", "船",
"瓶子", "巴士", "汽车", "猫", "椅子",
"牛", "餐桌", "狗", "马","摩托车", 
"人", "盆栽","羊", "沙发", "火车", "电视" };

上图中置信概率最高(0.999)的目标数组下标为2,对应的是bicycle自行车,只要大于设置的阈值(变量confidenceThreshold),就会在图像上标记出目标的位置(detectionMat行向量的3,4,5,6元素)。比如将阈值confidenceThreshold设置为0.5,则识别结果只有一个是大于0.5的,则只会在图像上标记出自行车,如下图:


实验效果

本地图片



相机实时

在相机上(普通的USB相机)会比较卡顿···,因为用的是CPU跑的,附上本人帅照···


附件

    源代码工程戳这里(注:release下的可执行程序可以直接运行)。


版权声明:本文为博主原创文章,转载请标明出处。 https://blog.csdn.net/KayChanGEEK/article/details/79978851

简单邮件传输协议SMTP封装类

简单邮件传输协议SMTP封装类作者:Asif Rasheed 翻译:刘建强 在Internet上,Email是最流行的传输媒体。这篇文章包括两个协议:. POP 3 协议: POP3协议(邮政传输协议...
  • ghj1976
  • ghj1976
  • 2001-08-22 18:15:00
  • 1438

利用OpenCV和深度学习实现人脸检测

本文基于OpenCV3.3.1或以上版本(如OpenCV3.4)、DNN模块和face_detector示例实现简单、实时的人脸检测。往期回顾[计算机视觉] 入门学习资料[计算机视觉论文速递] 201...
  • zhongranxu
  • zhongranxu
  • 2018-03-22 10:32:39
  • 104

SSD: Single Shot MultiBox Detector 检测单张图片

前言 博主也算是刚开始研究SSD项目,之前写了一篇SSD的安装和配置,这次是简单介绍下如何用SSD检测单张图片,其实过程也比较简单,下面正式开始。准备工作 当然,首先你要把SSD按照教程编译好,设置好...
  • Jesse_Mx
  • Jesse_Mx
  • 2016-10-29 16:39:05
  • 16419

opencv3.4.0的CMake需联外网下载的.cache文件夹内容(ippicv等)

  • 2017年12月26日 15:06
  • 109.97MB
  • 下载

caffe ssd

./build/examples/ssd/ssd_detect.bin models/VGGNet/deploy.prototxt models/VGGNet/VGG_VOC0712_SSD_300x...
  • ppp2006
  • ppp2006
  • 2016-09-18 09:57:51
  • 2785

opencv3.4 发布 dnnFace震撼来袭

在圣诞夜的前夕opencv发布了3.4版本,主要增强了dnn模块,特别是添加了对faster-rcnn的支持,并且带有openCL加速 我主要测试了下其中的resnetface示例,效果还不错,除了...
  • minstyrain
  • minstyrain
  • 2017-12-26 22:45:55
  • 1854

SSD: Single Shot MultiBox Detector检测单张图片

准备工作 当然,首先你要把SSD按照教程编译好,设置好python环境变量,然后重启计算机(建议),开始本次工作。SSD项目检测单张图片有C++程序和ipython程序,这里建议用ipython,主...
  • shawncheer
  • shawncheer
  • 2016-12-10 15:10:59
  • 2771

OpenCV学习笔记(六)OpenCV3.3+VS2013 配置CUDA加速

1、关于Cmake配置Cuda没什么好说的,大多数教程都说的很明白了,和VS配置出错大多都是vs版本问题,我之前使用VS2015编译一直编译出错,后来换成了VS2015就通过了。2、主要是现在很多教程...
  • qq_26625581
  • qq_26625581
  • 2018-02-08 11:42:46
  • 71

OpenCV dnn模块支持Caffe

#include #include #include using namespace cv; using namespace cv::dnn; #include #include #incl...
  • BBZZ2
  • BBZZ2
  • 2016-09-14 10:51:30
  • 1601

OpenCV 用dnn深度学习模块检测图像

最近在做人物目标检测相关的项目,发现OpenCV从3.1(或者更找)提供了dnn深度学习模块(需要自行编译进去,具体的可见这篇文章),因此下下来试试看。难度全在编译那边了,编译完成后反倒很简单,下面就...
  • oHanTanYanYing
  • oHanTanYanYing
  • 2017-04-29 18:17:25
  • 3140
收藏助手
不良信息举报
您举报文章:OpenCV-DNN使用SSD网络目标检测
举报原因:
原因补充:

(最多只允许输入30个字)