深度学习目标检测系列:一文弄懂YOLO算法|附Python源码

在之前的文章中,介绍了计算机视觉领域中目标检测的相关方法——RCNN系列算法原理,以及Faster RCNN的实现。这些算法面临的一个问题,不是端到端的模型,几个构件拼凑在一起组成整个检测系统,操作起来比较复杂,本文将介绍另外一个端到端的方法——YOLO算法,该方法操作简便且仿真速度快,效果也不差。

YOLO算法是什么?

       YOLO框架(You Only Look Once)与RCNN系列算法不一样,是以不同的方式处理对象检测。它将整个图像放在一个实例中,并预测这些框的边界框坐标和及所属类别概率。使用YOLO算法最大优的点是速度极快,每秒可处理45帧,也能够理解一般的对象表示。

YOLO框架如何运作?

       在本节中,将介绍YOLO用于检测给定图像中的对象的处理步骤。

  • 首先,输入图像:

 

  • 然后,YOLO将输入图像划分为网格形式(例如3 X 3):

 

  • 最后,对每个网格应用图像分类和定位处理,获得预测对象的边界框及其对应的类概率。

       整个过程是不是很清晰,下面逐一详细介绍。首先需要将标记数据传递给模型以进行训练。假设已将图像划分为大小为3 X 3的网格,且总共只有3个类别,分别是行人(c1)、汽车(c2)和摩托车(c3)。因此,对于每个单元格,标签y将是一个八维向量:


其中:

  • pc定义对象是否存在于网格中(存在的概率);
  • bx、by、bh、bw指定边界框;
  • c1、c2、c3代表类别。如果检测对象是汽车,则c2位置处的值将为1,c1和c3处的值将为0;

       假设从上面的例子中选择第一个网格:


       由于此网格中没有对象,因此pc将为零,此网格的y标签将为:


        意味着其它值是什么并不重要,因为网格中没有对象。下面举例另一个有车的网格(c2=1):


       在为此网格编写y标签之前,首先要了解YOLO如何确定网格中是否存在实际对象。大图中有两个物体(两辆车),因此YOLO将取这两个物体的中心点,物体将被分配到包含这些物体中心的网格中。中心点左侧网格的y标签会是这样的:


       由于此网格中存在对象,因此pc将等于1,bx、by、bh、bw将相对于正在处理的特定网格单元计算。由于检测出的对象是汽车,所以c2=1,c1和c3均为0。对于9个网格中的每一个单元格,都具有八维输出向量。最终的输出形状为3X3X8
       使用上面的例子(输入图像:100X100X3,输出:3X3X8),模型将按如下方式进行训练:


       使用经典的CNN网络构建模型,并进行模型训练。在测试阶段,将图像传递给模型,经过一次前向传播就得到输出y。为了简单起见,使用3X3网格解释这一点,但通常在实际场景中会采用更大的网格(比如19X19)。
       即使一个对象跨越多个网格,它也只会被分配到其中点所在的单个网格。可以通过增加更多网格来减少多个对象出现在同一网格单元中的几率。

如何编码边界框?

       如前所述,bx、by、bh和bw是相对于正在处理的网格单元计算而言的。下面通过一个例子来说明这一点。以包含汽车的右边网格为例:


       由于bx、by、bh和bw将仅相对于该网格计算。此网格的y标签将为:


       由于这个网格中有一个对象汽车,所以pc=1c2=1。现在,看看如何决定bx、by、bh和bw的取值。在YOLO中,分配给所有网格的坐标都如下图所示:


       bx、by是对象相对于该网格的中心点的x和y坐标。在例子中,近似bx=0.4by=0.3


       bh是边界框的高度与相应单元网格的高度之比,在例子中约为0.9:bh=0.9,bw是边界框的宽度与网格单元的宽度之比,bw=0.5。此网格的y标签将为:


       请注意,bx和by将始终介于0和1之间,因为中心点始终位于网格内,而在边界框的尺寸大于网格尺寸的情况下,bh和bw可以大于1。

非极大值抑制|Non-Max Suppression

       这里有一些思考的问题——如何判断预测的边界框是否是一个好结果(或一个坏结果)?单元格之间的交叉点,计算实际边界框和预测的边界框的并集交集。假设汽车的实际和预测边界框如下所示:


       其中,红色框是实际的边界框,蓝色框是预测的边界框。如何判断它是否是一个好的预测呢?IoU将计算这两个框的并集交叉区域:

  • IoU =交叉面积/联合的面积;
  • 在本例中:

    • IoU =黄色面积/绿色面积;

       如果IoU大于0.5,就可以说预测足够好。0.5是在这里采取的任意阈值,也可以根据具体问题进行更改。阈值越大,预测就越准确。
       还有一种技术可以显着提高YOLO的效果——非极大值抑制。
       对象检测算法最常见的问题之一是,它不是一次仅检测出一次对象,而可能获得多次检测结果。假设:


       上图中,汽车不止一次被识别,那么如何判定边界框呢。非极大值抑可以解决这个问题,使得每个对象只能进行一次检测。下面了解该方法的工作原理。

  • 1.它首先查看与每次检测相关的概率并取最大的概率。在上图中,0.9是最高概率,因此首先选择概率为0.9的方框:

 

  • 2.现在,它会查看图像中的所有其他框。与当前边界框较高的IoU的边界框将被抑制。因此,在示例中,0.6和0.7概率的边界框将被抑制:

 

  • 3.在部分边界框被抑制后,它会从概率最高的所有边界框中选择下一个,在例子中为0.8的边界框:

 

  • 4.再次计算与该边界框相连边界框的IoU,去掉较高IoU值的边界框:

 

  • 5.重复这些步骤,得到最后的边界框:

 

       以上就是非极大值抑制的全部内容,总结一下关于非极大值抑制算法的要点:

  • 丢弃概率小于或等于预定阈值(例如0.5)的所有方框;
  • 对于剩余的边界框:
  • 选择具有最高概率的边界框并将其作为输出预测;
  • 计算相关联的边界框的IoU值,舍去IoU大于阈值的边界框;
  • 重复步骤2,直到所有边界框都被视为输出预测或被舍弃;

Anchor Boxes

       在上述内容中,每个网格只能识别一个对象。但是如果单个网格中有多个对象呢?这就行需要了解 Anchor Boxes的概念。假设将下图按照3X3网格划分:


       获取对象的中心点,并根据其位置将对象分配给相应的网格。在上面的示例中,两个对象的中心点位于同一网格中:


       上述方法只会获得两个边界框其中的一个,但是如果使用Anchor Boxes,可能会输出两个边界框!我们该怎么做呢?首先,预先定义两种不同的形状,称为Anchor Boxes。对于每个网格将有两个输出。这里为了易于理解,这里选取两个Anchor Boxes,也可以根据实际情况增加Anchor Boxes的数量:

  • 没有Anchor Boxes的YOLO输出标签如下所示:

  • 有Anchor Boxes的YOLO输出标签如下所示:

 


       前8行属于Anchor Boxes1,其余8行属于Anchor Boxes2。基于边界框和框形状的相似性将对象分配给Anchor Boxes。由于Anchor Boxes1的形状类似于人的边界框,后者将被分配给Anchor Boxes1,并且车将被分配给Anchor Boxes2.在这种情况下的输出,将是3X3X16大小。
       因此,对于每个网格,可以根据Anchor Boxes的数量检测两个或更多个对象。

结合思想

       在本节中,首先介绍如何训练YOLO模型,然后是新的图像进行预测。

训练

       训练模型时,输入数据是由图像及其相应的y标签构成。样例如下:


       假设每个网格有两个Anchor Boxes,并划分为3X3网格,并且有3个不同的类别。因此,相应的y标签具有3X3X16的形状。训练过程的完成方式就是将特定形状的图像映射到对应3X3X16大小的目标。

测试

       对于每个网格,模型将预测·3X3X16·大小的输出。该预测中的16个值将与训练标签的格式相同。前8个值将对应于Anchor Boxes1,其中第一个值将是该网络中对象的概率,2-5的值将是该对象的边界框坐标,最后三个值表明对象属于哪个类。以此类推。
       最后,非极大值抑制方法将应用于预测框以获得每个对象的单个预测结果。
       以下是YOLO算法遵循的确切维度和步骤:

  • 准备对应的图像(608,608,3);
  • 将图像传递给卷积神经网络(CNN),该网络返回(19,19,5,85)维输出;
  • 输出的最后两个维度被展平以获得(19,19,425)的输出量:

    • 19×19网格的每个单元返回425个数字;
    • 425=5 * 85,其中5是每个网格的Anchor Boxes数量;
    • 85= 5+80,其中5表示(pc、bx、by、bh、bw),80是检测的类别数;
  • 最后,使用IoU和非极大值抑制去除重叠框;

YOLO算法实现

       本节中用于实现YOLO的代码来自Andrew NG的GitHub存储库,需要下载此zip文件,其中包含运行此代码所需的预训练权重。
       首先定义一些函数,这些函数将用来选择高于某个阈值的边界框,并对其应用非极大值抑制。首先,导入所需的库:

import os
import matplotlib.pyplot as plt
from matplotlib.pyplot import imshow
import scipy.io
import scipy.misc
import numpy as np
import pandas as pd
import PIL
import tensorflow as tf
from skimage.transform import resize
from keras import backend as K
from keras.layers import Input, Lambda, Conv2D
from keras.models import load_model, Model
from yolo_utils import read_classes, read_anchors, generate_colors, preprocess_image, draw_boxes, scale_boxes
from yad2k.models.keras_yolo import yolo_head, yolo_boxes_to_corners, preprocess_true_boxes, yolo_loss, yolo_body%matplotlib inline

然后,实现基于概率和阈值过滤边界框的函数:

def yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = .6):box_scores = box_confidence*box_class_probsbox_classes = K.argmax(box_scores,-1)box_class_scores = K.max(box_scores,-1)filtering_mask = box_class_scores>thresholdscores = tf.boolean_mask(box_class_scores,filtering_mask)boxes = tf.boolean_mask(boxes,filtering_mask)classes = tf.boolean_mask(box_classes,filtering_mask)return scores, boxes, classes

之后,实现计算IoU的函数:

def iou(box1, box2):xi1 = max(box1[0],box2[0])yi1 = max(box1[1],box2[1])xi2 = min(box1[2],box2[2])yi2 = min(box1[3],box2[3])inter_area = (yi2-yi1)*(xi2-xi1)box1_area = (box1[3]-box1[1])*(box1[2]-box1[0])box2_area = (box2[3]-box2[1])*(box2[2]-box2[0])union_area = box1_area+box2_area-inter_areaiou = inter_area/union_areareturn iou

然后,实现非极大值抑制的函数:

def yolo_non_max_suppression(scores, boxes, classes, max_boxes = 10, iou_threshold = 0.5):max_boxes_tensor = K.variable(max_boxes, dtype='int32')K.get_session().run(tf.variables_initializer([max_boxes_tensor]))nms_indices = tf.image.non_max_suppression(boxes,scores,max_boxes,iou_threshold)scores = K.gather(scores,nms_indices)boxes = K.gather(boxes,nms_indices)classes = K.gather(classes,nms_indices)return scores, boxes, classes

随机初始化下大小为(19,19,5,85)的输出向量:

yolo_outputs = (tf.random_normal([19, 19, 5, 1], mean=1, stddev=4, seed = 1),tf.random_normal([19, 19, 5, 2], mean=1, stddev=4, seed = 1),tf.random_normal([19, 19, 5, 2], mean=1, stddev=4, seed = 1),tf.random_normal([19, 19, 5, 80], mean=1, stddev=4, seed = 1))

最后,实现一个将CNN的输出作为输入并返回被抑制的边界框的函数:

def yolo_eval(yolo_outputs, image_shape = (720., 1280.), max_boxes=10, score_threshold=.6, iou_threshold=.5):box_confidence, box_xy, box_wh, box_class_probs = yolo_outputsboxes = yolo_boxes_to_corners(box_xy, box_wh)scores, boxes, classes = yolo_filter_boxes(box_confidence, boxes, box_class_probs, threshold = score_threshold)boxes = scale_boxes(boxes, image_shape)scores, boxes, classes = yolo_non_max_suppression(scores, boxes, classes, max_boxes, iou_threshold)return scores, boxes, classes

使用yolo_eval函数对之前创建的随机输出向量进行预测:

scores, boxes, classes = yolo_eval(yolo_outputs)
with tf.Session() as test_b:print("scores[2] = " + str(scores[2].eval()))print("boxes[2] = " + str(boxes[2].eval()))print("classes[2] = " + str(classes[2].eval()))

 

29


score表示对象在图像中的可能性,boxes返回检测到的对象的(x1,y1,x2,y2)坐标,classes表示识别对象所属的类。
现在,在新的图像上使用预训练的YOLO算法,看看其工作效果:

sess = K.get_session()
class_names = read_classes("model_data/coco_classes.txt")
anchors = read_anchors("model_data/yolo_anchors.txt")yolo_model = load_model("model_data/yolo.h5")

在加载类别信息和预训练模型之后,使用上面定义的函数来获取·yolo_outputs·。

yolo_outputs = yolo_head(yolo_model.output, anchors, len(class_names))

之后,定义一个函数来预测边界框并在图像上标记边界框:

def predict(sess, image_file):image, image_data = preprocess_image("images/" + image_file, model_image_size = (608, 608))out_scores, out_boxes, out_classes = sess.run([scores, boxes, classes], feed_dict={yolo_model.input: image_data, K.learning_phase(): 0})print('Found {} boxes for {}'.format(len(out_boxes), image_file))# Generate colors for drawing bounding boxes.colors = generate_colors(class_names)# Draw bounding boxes on the image filedraw_boxes(image, out_scores, out_boxes, out_classes, class_names, colors)# Save the predicted bounding box on the imageimage.save(os.path.join("out", image_file), quality=90)# Display the results in the notebookoutput_image = scipy.misc.imread(os.path.join("out", image_file))plt.figure(figsize=(12,12))imshow(output_image)return out_scores, out_boxes, out_classes

接下来,将使用预测函数读取图像并进行预测:

img = plt.imread('images/img.jpg')
image_shape = float(img.shape[0]), float(img.shape[1])
scores, boxes, classes = yolo_eval(yolo_outputs, image_shape)

最后,输出预测结果:

out_scores, out_boxes, out_classes = predict(sess, "img.jpg")

 


以上就是YOLO算法的全部内容

 


原文链接
本文为云栖社区原创内容,未经允许不得转载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/520244.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Keepalived时主备负载均衡器都有VIP的问题:VRRP协议问题

文章目录一、企业案例背景二、异常现象三、分析结论解决思路3.1. 分析结论3.2. 解决思路四、SElinux 处理4.1. 查看SElinux的状态:4.2. 关闭SElinux五、Firewalld防火墙配置5.1. 开启vrrp 协议5.2. 重新启动防火墙5.3. 查看启动日志5.4. 虚拟ip验证5.5. 停止master节…

数据不足,如何进行迁移学习?

现在,人工智能的发展处于跳跃式阶段,我们也对AI在大型数据集的应用进展感到吃惊。更重要的是,那些我们没有跟踪的数十亿张照片或餐厅的评论并没有被遗漏掉:迁移学习技术让收集数据变得更加“容易”。另外,得益于PyTorc…

MongoDB+阿里云 最新数据库独家上线!

近日,开源数据库厂商MongoDB与阿里云在北京达成战略合作,作为合作的第一步,最新版MongoDB 4.2数据库产品正式上线阿里云平台。 目前阿里云成为全球唯一可提供最新版MongoDB服务的云厂商,双方合作打通了企业在云上使用最新版开源数…

一天超2000次,阿里如何打响音视频超时空战役?

在阿里,音视频会议已经成为跨地区沟通、开会以及招聘的首选方式。据悉,目前阿里巴巴的办公网络与音视频会议已经覆盖全球33个国家和地区,其中,音视频会议在过去3个月平均每天召开超过2000余场。在使用如此频繁、覆盖面如此之广的音…

java pppoe_PPPoE拨号流程

PPP会话的建立,需要两端的设备都发送LCP数据包来配置和测试数据通信链路。用户主机与接入集中器根据在发现阶段所协商的PPP会话连接参数进行PPP会话。一旦PPPoE会话开始,PPP数据就可以以任何其他的PPP封装形式发送。所有的以太网帧都是单播的。PPPoE会话…

Flutter路由管理代码这么长长长长长,阿里工程师怎么高效解决?(实用)

背景: 在flutter的业务开发过程中,flutter侧会逐渐丰富自己的路由管理。一个轻量的路由管理本质上是页面标识(或页面路径)与页面实例的映射。本文基于dart注解提供了一个轻量路由管理方案。 不论是在native与flutter的混合工程&…

用PyTorch创建一个图像分类器?So easy!(Part 1)

经过了几个月的学习和实践,我完成了优达学城网站上《Python Programming with Python Nanodegree》课程的学习,该课程的终极项目就是使用Pytorch为102种不同类型的花创建一个图像分类器。 在完成这个项目的过程中,我和其他学员一样&#xff…

阿里上市,四大洲8个国家的十位代表敲锣;全球首款支持5G双卡双待的芯片发布;撕裂者3990X:桌面史上第一次64核128线程……...

关注并标星星CSDN云计算速递、最新、绝对有料。这里有企业新动、这里有业界要闻,打起十二分精神,紧跟fashion你可以的!每周两次,打卡即read更快、更全了解泛云圈精彩newsgo go govivo X30新细节曝光:搭载潜望式超远摄支…

支付宝客户端架构分析:自动化日志收集及分析

小蚂蚁说: 《支付宝客户端架构解析》系列将从支付宝客户端的架构设计方案入手,细分拆解客户端在“容器化框架设计”、“网络优化”、“性能启动优化”、“自动化日志收集”、“RPC 组件设计”、“移动应用监控、诊断、定位”等具体实现,带领…

在Kubernetes上运行区块链服务(BaaS)

本文是在2018年11月15日由Linux基金会CNCF主办的KubeCon & CloudNativeCon China 2018大会的“Running Blockchain as a Service (BaaS) on Kubernetes”演讲内容基础上整理而成,从技术上介绍了阿里云如何将基于区块链Hyperledger Fabric的BaaS和容器集群技术Ku…

RabbitMQ 镜像集群之同步策略_专栏讲解

文章目录一、 基础知识汲取1.1. 镜像集群简述1.2. 策略参数说明1.3. 策略案例二、HA mode 同步方式2.1. 参数说明2.2. 案例2.3. 命令终端形式2.4. MQ管控台设置2.5. 队列同步2.5. 优缺点三、Ha async mode 同步方式(推荐使用)3.1. 参数说明3.2. 案例3.3.…

bug要改一天?

大家应该都听过下面的一个段子~女生:亲爱的,我来亲戚了男生:多喝热水......女生:我好像要感冒了,亲爱的~男生:多喝热水......女生:我现在好难受哦,快撑不下去了男生:多喝…

新手也能看懂,消息队列其实很简单

本文内容思维导图: 消息队列其实很简单 “RabbitMQ?”“Kafka?”“RocketMQ?”...在日常学习与开发过程中,我们常常听到消息队列这个关键词。我也在我的多篇文章中提到了这个概念。可能你是熟练使用消息队列的老手&am…

如何去设计前端框架能力?星巴克消息开放项目从0到1,从点到面的思考

本文由淘宝前端工程师罗嗣分享,主要讲述了作者在星巴克消息开放项目中的总结和思考,希望对大家有帮助,让业务分享更加有价值。 从满足星巴克项目需求单点出发,发散到从点到面的思考。从而总结了自己思考的基本流程(方法…

如何在springboot中使用PageHelper分页插件

文章目录1. pom依赖2. yml3. 实体类4. mapper映射文件4. mapper接口5. service接口6. 实现类7. controller8. 浏览器验证使用思路: 1.引入myabtis和pagehelper依赖 2.yml中配置mybatis扫描和实体类 3. 这2行代码 pageNum:当前第几页 pageNum:…

6.6折票仅剩3天 | BDTC 2019全日程公布,哪些是你感兴趣的话题?

2019年12月5-7日,由中国计算机学会主办,CCF 大数据专家委员会承办,CSDN、中科天玑数据科技股份有限公司协办的中国大数据技术大会(BDTC 2019)将于北京长城饭店隆重举行。届时,超过百位顶尖技术专家将齐聚于…

java线程条件变量_使用条件变量(多线程笔记)

条件变量属性:使用条件变量可以以原子方式阻塞线程,知道某个特定条件为真为止。条件变量始终与互斥锁一起使用。使用条件变量,线程可以以原子方式阻塞,知道满足某个条件为止。对掉件的测试时在互斥锁的保护下进行的。如果条件为假…

用PyTorch创建一个图像分类器?So easy!(Part 2)

在第一部分中,我们知道了为什么以及如何加载预先训练好的神经网络,我们可以用自己的分类器代替已有神经网络的分类器。那么,在这篇文章中,我们将学习如何训练分类器。 训练分类器 首先,我们需要为分类器提供待分类的…

涨姿势,一个通信项目从开始到结束,原来还包括这些工作

戳蓝字“CSDN云计算”关注我们哦!作者 | 小枣君责编 | 阿秃本月12日,中国移动31个省的通信工程设计与可行性研究集采正式启动。这次集采规模庞大,涵盖了无线网(5G、FDD、NB等)、核心网、承载网、支撑网等专业方向,预估基本规模超4…

听说支付宝有一个“疯起来连自己都打”的项目

小蚂蚁说: 自古红蓝出CP,在蚂蚁金服就有这样两支“相爱相杀”的队伍——红军和蓝军。蓝军是进攻方,主要职责是挖掘系统的弱点并发起“真实”的攻击,俗称“找茬”;红军则是防守方,其防控体系建设中的实时核…