OpenCV3.3 深度学习模块-对象检测演示
时间:2022-05-07
本文章向大家介绍OpenCV3.3 深度学习模块-对象检测演示,主要内容包括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自带的视频为例,运行截图:
四:演示代码
相关注释已经写在代码里面,不在多废话、解释!代码即文档!
int main(int argc, char** argv) {
Mat frame = imread("D:/vcprojects/images/dnn/004545.jpg");
// Mat frame = imread("D:/vcprojects/images/paiqiu.png");
// Mat frame = imread("D:/vcprojects/images/dnn/000456.jpg");
// Mat frame = imread("D:/vcprojects/images/ssd.jpg");
if (frame.empty()) {
printf("could not load image...n");
return -1;
}
// 读取分类文本标记
Ptr<dnn::Importer> importer;
vector<String> text_labels = readClasslabels();
// Import Caffe SSD model
try
{
importer = dnn::createCaffeImporter(modelConfiguration, modelBinary);
}
catch (const cv::Exception &err)
{
cerr << err.msg << endl;
}
// 初始化网络
dnn::Net net;
importer->populateNet(net);
importer.release();
// 准备输入数据,
Mat preprocessedFrame = preprocess(frame); // 300x300 resize substract means
Mat inputBlob = blobFromImage(preprocessedFrame);
// 检测
net.setInput(inputBlob, "data"); // 输入层 data
Mat detection = net.forward("detection_out"); // 输出到最后一层
Mat detectionMat(detection.size[2], detection.size[3], CV_32F, detection.ptr<float>());
// 根据置信阈值设置,绘制对象矩形
float confidenceThreshold = 0.1;
for (int i = 0; i < detectionMat.rows; i++)
{
float confidence = detectionMat.at<float>(i, 2);
// printf("current confidence %.2f n", confidence);
if (confidence > confidenceThreshold)
{
size_t objectClass = (size_t)(detectionMat.at<float>(i, 1));
float xLeftBottom = detectionMat.at<float>(i, 3) * frame.cols;
float yLeftBottom = detectionMat.at<float>(i, 4) * frame.rows;
float xRightTop = detectionMat.at<float>(i, 5) * frame.cols;
float yRightTop = detectionMat.at<float>(i, 6) * frame.rows;
// 得到分类ID与置信值
std::cout << "Class: " << objectClass << std::endl;
std::cout << "Confidence: " << confidence << std::endl;
std::cout << " " << xLeftBottom
<< " " << yLeftBottom
<< " " << xRightTop
<< " " << yRightTop << std::endl;
Rect object((int)xLeftBottom, (int)yLeftBottom,
(int)(xRightTop - xLeftBottom),
(int)(yRightTop - yLeftBottom));
// 绘制矩形与分类文本
rectangle(frame, object, Scalar(0, 0, 255), 2, 8, 0);
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);
}
}
imshow("detections", frame);
waitKey(0);
return 0;
}
其中读取分类标记文档代码如下:
/* 读取图像的100个分类标记文本数据 */
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() && (name.find("display_name:") == 0)) {
string temp = name.substr(15);
temp.replace(temp.end()-1, temp.end(), "");
printf("current row content %sn", temp.c_str());
classNames.push_back(temp);
}
}
fp.close();
return classNames;
}
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 1024程序员节 | 我在腾讯自研数据库,我为技术代言
- jasmine spyOn的单步调试
- codeforces 1363C(优先队列)
- 系统与应用异常定位诊断
- SQL优化终于干掉了“distinct”
- SAP Spartacus delivery mode页面Cannot find control with的错误消息
- codeforces 1349A(数学)
- 阔别两年,webpack 5 正式发布了!
- SAP Spartacus delivery mode continue button enable与否的逻辑
- codeforces 1342C(前缀和)
- leetcode-寻找两个正序数组的中位数
- Shell脚本常用命令一览
- 深入学习 React 合成事件
- 关于fixture.debugElement.query(By.css)这个方法的一个疑问
- codeforces 1334C(前缀和)