深度学习目标检测系列:一文弄懂YOLO算法 |
您所在的位置:网站首页 › 一键远程桌面命令 › 深度学习目标检测系列:一文弄懂YOLO算法 |
在之前的文章中,介绍了计算机视觉领域中目标检测的相关方法——RCNN系列算法原理,以及Faster RCNN的实现。这些算法面临的一个问题,不是端到端的模型,几个构件拼凑在一起组成整个检测系统,操作起来比较复杂,本文将介绍另外一个端到端的方法——YOLO算法,该方法操作简便且仿真速度快,效果也不差。 YOLO框架(You Only Look Once)与RCNN系列算法不一样,是以不同的方式处理对象检测。它将整个图像放在一个实例中,并预测这些框的边界框坐标和及所属类别概率。使用YOLO算法最大优的点是速度极快,每秒可处理45帧,也能够理解一般的对象表示。 YOLO框架如何运作?在本节中,将介绍YOLO用于检测给定图像中的对象的处理步骤。 首先,输入图像:整个过程是不是很清晰,下面逐一详细介绍。首先需要将标记数据传递给模型以进行训练。假设已将图像划分为大小为3 X 3的网格,且总共只有3个类别,分别是行人(c1)、汽车(c2)和摩托车(c3)。因此,对于每个单元格,标签y将是一个八维向量: 假设从上面的例子中选择第一个网格: 如前所述,bx、by、bh和bw是相对于正在处理的网格单元计算而言的。下面通过一个例子来说明这一点。以包含汽车的右边网格为例: 这里有一些思考的问题——如何判断预测的边界框是否是一个好结果(或一个坏结果)?单元格之间的交叉点,计算实际边界框和预测的边界框的并集交集。假设汽车的实际和预测边界框如下所示: 在本例中: IoU =黄色面积/绿色面积;如果IoU大于0.5,就可以说预测足够好。0.5是在这里采取的任意阈值,也可以根据具体问题进行更改。阈值越大,预测就越准确。 还有一种技术可以显着提高YOLO的效果——非极大值抑制。 对象检测算法最常见的问题之一是,它不是一次仅检测出一次对象,而可能获得多次检测结果。假设: 以上就是非极大值抑制的全部内容,总结一下关于非极大值抑制算法的要点: 丢弃概率小于或等于预定阈值(例如0.5)的所有方框; 对于剩余的边界框: 选择具有最高概率的边界框并将其作为输出预测; 计算相关联的边界框的IoU值,舍去IoU大于阈值的边界框; 重复步骤2,直到所有边界框都被视为输出预测或被舍弃; Anchor Boxes在上述内容中,每个网格只能识别一个对象。但是如果单个网格中有多个对象呢?这就行需要了解 Anchor Boxes的概念。假设将下图按照3X3网格划分: 在本节中,首先介绍如何训练YOLO模型,然后是新的图像进行预测。 训练训练模型时,输入数据是由图像及其相应的y标签构成。样例如下: 对于每个网格,模型将预测·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_probs box_classes = K.argmax(box_scores,-1) box_class_scores = K.max(box_scores,-1) filtering_mask = box_class_scores>threshold scores = 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_area iou = inter_area/union_area return 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_outputs boxes = 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()))在加载类别信息和预训练模型之后,使用上面定义的函数来获取·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 file draw_boxes(image, out_scores, out_boxes, out_classes, class_names, colors) # Save the predicted bounding box on the image image.save(os.path.join("out", image_file), quality=90) # Display the results in the notebook output_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")PULKIT SHARMA,机器学习和深度学习本文由阿里云云栖社区组织翻译。文章原标题《A Practical Guide to Object Detection using the Popular YOLO Framework – Part III (with Python codes)》,译者:海棠,审校:Uncle_LLD。文章为简译,更为详细的内容,请查看原文。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |