博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【YOLO学习笔记】之YOLO初体验
阅读量:4075 次
发布时间:2019-05-25

本文共 6233 字,大约阅读时间需要 20 分钟。

前言

因为要完成毕业论文,所以最近正在学习计算机视觉,如果大家有什么问题,都可以跟我沟通交流。除了通过博客交流外,欢迎你加入我的QQ群,一起交流有关于机器学习、深度学习、计算机视觉有关内容。目前我并未确定具体的研究方向,所以现在处于广泛涉猎阶段,希望我们能够一起沟通。下图是我的群二维码:

马上就要开始写毕业论文了,定题目是一件很痛苦的事情,普通的管理系统不想写(根本原因在于没有架构思维,没有真正的软件工程思想,不懂业务需求,不明白业务逻辑,不想写一个所谓的管理系统糊弄事)所以上网查阅资料,问同学,终于,我和YOLO邂逅了。

所以小编开始上网查找YOLO,然后。。。。

(笑十分钟,写什么毕业论文,享受人生去,不得不说,这个学期,事挺多的,是有点忙不过来,但是该做的还得做啊。)

那YOLO是什么呢?且听我慢慢道来。

一、YOLO怎么出生的?

1、出生前

在深度神经网络之前,早期的 Object detection (目标检测)方法是通过提取图像的一些 robust 的特征如( Haar,SIFT,HOG )等特征,使用 DPM 模型,用 silding window 的方式来预测具有较高 score 的 bounding box。这种方式非常耗时,而且精度又不怎么高。

有用过OpenCV的童鞋,可能了解过,OpenCV自带脸部检测功能,用到的就是Haar分类器。

后来出现了CNN,RCNN等神经网络,精度大幅度提高(逼格也大幅度提高)。

2、出生时——YOLO v1

2015年,Joseph Redmon和Ali Farhadi等人提出的基于单个神经网络的目标检测系统,完成了著名的论文《You Only Look Once: Unified, Real-Time Object Detection》,即我们今天所用的第一个版本YOLO v1。这是继 RCNN,fast-RCNN 和 faster-RCNN之后,Ross Girshick 针对 DL 目标检测速度问题提出的另外一种框架。YOLO V1 其增强版本在 GPU 上能跑45fps,简化版本155fps。

论文下载:

代码下载: 

3、第一次“升级”——YOLO v2

为提高物体定位精准性和召回率,YOLO作者在2017年的CVPR发表论文 《YOLO9000: Better, Faster, Stronger》 即提出了YOLO v2,相比v1提高了训练图像的分辨率;引入了faster rcnn中anchor box的思想,对网络结构的设计进行了改进,输出层使用卷积层替代YOLO的全连接层,联合使用coco物体检测标注数据和imagenet物体分类标注数据训练物体检测模型。相比YOLO,YOLO9000在识别种类、精度、速度、和定位准确性等方面都有大大提升。

4、第二次“升级”——YOLO v3

后来,YOLO作者进一步推出v3,速度更快,准确度更高,YOLO V3在Pascal Titan X上处理608x608图像速度达到20FPS,在 COCO test-dev 上 mAP@0.5 达到 57.9%,与RetinaNet的结果相近,并且速度快了4倍。  YOLO V3的模型比之前的模型复杂了不少,可以通过改变模型结构的大小来权衡速度与精度。有图为证:

作者对YOLO v3的赞赏如下:

YOLOv3 is extremely fast and accurate. In mAP measured at .5 IOU YOLOv3 is on par with Focal Loss but about 4x faster. Moreover, you can easily tradeoff between speed and accuracy simply by changing the size of the model, no retraining required.

二、YOLO怎么使用

开山之作YOLO v1,它的出生就决定了它的独特所在,相比R-CNN、Fast R-CNN,它有着自己独特的魅力,以至于V2,V3急速火爆。

但是我们想对YOLO有一个深入的了解,当然是先使用一下,了解一下它用起来怎么样,通过实战,来一步一步深入了解,深入学习YOLO。

1、配置

配置最重要,特别是我们要做的是深度学习与计算机视觉,不仅要求硬件,还要求软件。

在这里,我们不需要一个特别强大的GPU(有了最好),一个win7或者win10的电脑(win8也可以,但是win8现在很少使用,大多数程序员都偏爱win7)

我个人偏爱C++,所以我的编程语言用的是C++,如果各位对java,Python或者其他适合深度学习、人工智能的编程语言,大家可以根据原理自己编写,希望大家能够集思广益。

软件要求如下:

VS2015:网上下载,多的很,然后上网查找密钥登陆即可永久免费。

OpenCV3.4.0:

YOLO相关文件:(同时附赠本文所有源码)

安装及配置教程:请点击,即可查看。

2、代码解析

1.头文件

关于头文件的引用,因为用到黑窗体,需要输入输出,还要涉及到图形图像处理,需要调用opencv的一些头文件需要应用文件处理,文件处理相关头文件……

#pragma once#include"stdafx.h"#include
#include
#include
#include
#include
#include
using namespace std;using namespace cv;using namespace cv::dnn;

2.全局变量

还需要用到一些全局变量,yolov2-tiny-voc.cfg是YOLO的配置文件(后续会有详细讲解),yolov2-tiny-voc.weights是作者训练出来的权重文件,用来识别物体,比如下面这个图像上的是猫。

voc.names是YOLO作者在YOLO V1 中训练出来的20种物体的一个集合,包括:aeroplane、bicycle、bird、boat、bottle、bus、car、cat、chair、cow、diningtable、dog、horse、motorbike、person、pottedplant、sheep、sofa、train、tvmonitor。

float confidenceThreshold = 0.1;String modelConfiguration = "yolov2-tiny-voc.cfg";//yolov2-tiny-voc.cfgString modelBinary = "yolov2-tiny-voc.weights";ifstream classNamesFile("voc.names");

这些文件都可以在我上面的链接下载使用,解压到cpp文件所在文件夹。

3.函数定义

做测试主要是对图像和视频的测试,图像就是通过imread获取图片,视频通过摄像头获取视频流。所以我定义了两个函数,在这里我没有优化,只是为了大家能够理解YOLO,而不是学习提升C++的编程能力。

int dnn_yolo_syx_Img();int dnn_yolo_syx_Cam();

到这里,所有的前期准备工作,准备完成,接下来就是具体代码的理解,

4.函数实现

首先需要读入YOLO相关文件。

dnn::Net net = readNetFromDarknet(modelConfiguration, modelBinary);	//判断是否读入成功	if (net.empty())	{		printf("Could not load net...\n");		return -1;	}

然后需要定义一个数组,用于存放20个可识别的种类。

//定义一个string类的数组	vector
classNamesVec; if (classNamesFile.is_open()) { string className = ""; while (std::getline(classNamesFile, className)) classNamesVec.push_back(className); }

载入要识别的图像(小猫),并做一些处理

// 加载图像	Mat frame = imread("111.jpg");	if (frame.empty())	{		printf("Could not load image...\n");		return -1;	}	Mat inputBlob;	inputBlob = blobFromImage(frame, 1 / 255.F, Size(416, 416), Scalar(), true, false);	net.setInput(inputBlob, "data");

接下来是对图像上的物体做检测,并实时推送检测消耗时间。

// 检测	Mat detectionMat = net.forward("detection_out");	vector
layersTimings; double freq = getTickFrequency() / 1000; double time = net.getPerfProfile(layersTimings) / freq; ostringstream ss; ss << "detection time: " << time << " ms"; putText(frame, ss.str(), Point(20, 20), 0, 0.5, Scalar(0, 0, 255));

找到图像后,需要将图像标出,一个是用矩形将识别出来的物体标出,一个是检测物体,标出物体是什么。

// 输出结果	for (int i = 0; i < detectionMat.rows; i++)	{		const int probability_index = 5;		const int probability_size = detectionMat.cols - probability_index;		float *prob_array_ptr = &detectionMat.at
(i, probability_index); size_t objectClass = max_element(prob_array_ptr, prob_array_ptr + probability_size) - prob_array_ptr; float confidence = detectionMat.at
(i, (int)objectClass + probability_index); if (confidence > confidenceThreshold) { //语句见下一个代码块 } }

由于这段代码有点多,所以就分开来写,方便大家看懂其中的逻辑关系,下面是if语句里面的详细内容

if (confidence > confidenceThreshold)		{			float x = detectionMat.at
(i, 0); float y = detectionMat.at
(i, 1); float width = detectionMat.at
(i, 2); float height = detectionMat.at
(i, 3); int xLeftBottom = static_cast
((x - width / 2) * frame.cols); int yLeftBottom = static_cast
((y - height / 2) * frame.rows); int xRightTop = static_cast
((x + width / 2) * frame.cols); int yRightTop = static_cast
((y + height / 2) * frame.rows); Rect object(xLeftBottom, yLeftBottom, xRightTop - xLeftBottom, yRightTop - yLeftBottom); rectangle(frame, object, Scalar(0, 0, 255), 2, 8); if (objectClass < classNamesVec.size()) { } }

在上一个if语句块中还有一个if语句,详细内容如下:

if (objectClass < classNamesVec.size())	{		ss.str("");		ss << confidence;		String conf(ss.str());		String label = String(classNamesVec[objectClass]) + ": " + conf;		int baseLine = 0;		Size labelSize = getTextSize(label, CV_FONT_HERSHEY_SIMPLEX, 0.5, 1, &baseLine);		rectangle(frame, Rect(Point(xLeftBottom, yLeftBottom),			Size(labelSize.width, labelSize.height + baseLine)),			Scalar(255, 255, 255), CV_FILLED);		putText(frame, label, Point(xLeftBottom, yLeftBottom + labelSize.height),			CV_FONT_HERSHEY_SIMPLEX, 0.5, Scalar(0, 0, 0));	}

最后就是将图像输出,让大家能够看到结果。

imshow("YOLO-Detections", frame);	waitKey(0);	return 0;

输出图像如下:

大家可以自己写一下如何将上面的代码转化成识别摄像头读取的图像中的物体是什么?具体代码,大家也可以在YOLO相关文件中查找,大家有什么问题也可以在下面评论,我们一起相互交流。

 

 

 

 

 

 

 

你可能感兴趣的文章
coursesa课程 Python 3 programming course_2_assessment_7 多参数函数练习题
查看>>
coursesa课程 Python 3 programming course_2_assessment_8 sorted练习题
查看>>
多线程使用随机函数需要注意的一点
查看>>
getpeername,getsockname
查看>>
所谓的进步和提升,就是完成认知升级
查看>>
如何用好碎片化时间,让思维更有效率?
查看>>
No.182 - LeetCode1325 - C指针的魅力
查看>>
Encoding Schemes
查看>>
带WiringPi库的交叉笔译如何处理二之软链接概念
查看>>
Java8 HashMap集合解析
查看>>
自定义 select 下拉框 多选插件
查看>>
linux和windows内存布局验证
查看>>
Linux常用统计命令之wc
查看>>
fastcgi_param 详解
查看>>
搞定Java面试中的数据结构问题
查看>>
React Native(一):搭建开发环境、出Hello World
查看>>
React Native(二):属性、状态
查看>>
JSX使用总结
查看>>
React Native(四):布局(使用Flexbox)
查看>>
React Native(七):Android双击Back键退出应用
查看>>