做者|GUEST
编译|VK
来源|Analytics Vidhyapython
目标检测是计算机视觉中一个很是重要的领域,对于自动驾驶、视频监控、医疗应用和许多其余领域都是必要的。git
咱们正在与一场规模空前的传染病做斗争。全世界的研究人员都在试图开发一种疫苗或治疗COVID-19的方法,而医生们却在努力阻止这场传染病席卷全世界。另外一方面,许多国家发现了社会距离的疏远,使用口罩和手套能够稍微遏制这种局面。github
我最近有一个想法,用个人深度学习知识来帮助目前的状况。在这篇文章中,我将向你介绍RetinaNet的实现,背景知识很少。bash
咱们将使用RetinaNet创建一个“口罩探测器”来帮助咱们应对这场持续的传染病。你能够推断出一样的想法来为你的智能家居构建一个支持人工智能的解决方案。这我的工智能的解决方案只对戴着口罩和手套的人敞开大门。网络
随着无人机的成本随着时间的推移而下降,咱们看到空中数据的生成出现了一个大的峰值。所以,你可使用这个RetinaNet模型在航空图像甚至卫星图像中检测不一样的对象,如汽车(自行车、汽车等)或行人,以解决不一样的业务问题。架构
因此,你看目标检测模型的应用是无穷无尽的。app
RetinaNet的架构框架
利用RetinaNet模型创建口罩检测器dom
RetinaNet是一种最好的单目标检测模型,已被证实能很好地处理密集和小尺度的物体。因为这个缘由,它已经成为一个流行的目标检测模型。机器学习
RetinaNet是由Facebook人工智能研究所(Facebook-AI-Research)引入的,旨在解决密集检测问题。在处理极端前景-背景类时,须要弥补YOLO和SSD等单步目标检测器的不平衡和不一致。
从本质上讲,RetinaNet是一个复合网络,由如下部分组成:
为了更好地理解,让咱们分别了解架构的每一个组件
每一个FPN层都附加一个全卷积网络(FCN)进行对象分类。如图所示,该子网包含3*3个卷积层,256个滤波器,而后是3*3个卷积层,K*A滤波器,所以输出的feature map大小为W*H*KA,其中W和H与输入特征图的宽度和高度成比例,K和A分别为对象类和锚盒的数量。
最后利用Sigmoid层(而不是softmax)进行目标分类。
而最后一个卷积层之因此有KA滤波器是由于,若是从最后一个卷积层获得的特征图中的每一个位置都有不少锚盒候选区域,那么每一个锚盒都有可能被分类为K个类。因此输出的特征图大小将是KA通道或过滤器。
回归子网与分类子网并行附着在FPN的每一个特征图上。回归子网的设计与分类子网相同,只是最后一个卷积层大小为3*3,有4个filter,输出的特征图大小为W*H*4A。
最后一个卷积层有4个过滤器的缘由是,为了定位类对象,回归子网络为每一个锚定盒产生4个数字,这些数字预测锚定盒和真实框锚盒之间的相对偏移量(根据中心坐标、宽度和高度)。所以,回归子网的输出特征图具备4A滤波器或通道。
Focal Loss(FL)是Cross-Entropy Loss(CE)的改进版本,它经过为困难的或容易错误分类的示例(即具备嘈杂纹理或部分对象或咱们感兴趣的对象的背景)分配更多权重来尝试处理类不平衡问题 ,并简化简单的示例(即背景对象)。
所以,“Focal Loss”减小了简单示例带来的损失贡献,并提升了纠正错误分类的示例的重要性。 焦点损失只是交叉熵损失函数的扩展,它将下降简单示例的权重,并将训练重点放在困难样本上。
因此为了实现这些研究人员提出了
1- pt表明交叉熵损失,可调聚焦参数≥0。 RetinaNet物体检测方法使用焦距损失的α平衡变体,其中α= 0.25,γ= 2效果最佳。
因此Focal Loss能够定义为
请参见图,对于γ∈[0,5]的几个值,咱们将注意到Focal Loss的如下特性:
注:何时γ=0,FL至关于CE。图中所示为蓝色曲线
直观地看,调制因子减少了简单例的损耗贡献,扩展了例的低损耗范围。
如今让咱们看看用Python实现RetinaNet来构建口罩检测器。
任何深度学习模型都须要大量的训练数据才能在测试数据上产生良好的结果。
咱们开始使用LabelImg工具建立数据集和验证。这个优秀的注释工具可让你快速地注释对象的边界框,从而训练机器学习模型。
你能够在anaconda命令提示符下使用下面的命令安装它
pip install labelImg
你可使用下面的labelmg工具对每一个JPEG文件进行注释,它将生成带有每一个边界框坐标的XML文件。咱们将使用这些xml文件来训练咱们的模型。
import os print(os.getcwd())
git clone https://github.com/fizyr/keras-retinanet.git %cd keras-retinanet/ !pip install . !python setup.py build_ext --inplace
import numpy as np import shutil import pandas as pd import os, sys, random import xml.etree.ElementTree as ET import pandas as pd from os import listdir from os.path import isfile, join import matplotlib.pyplot as plt from PIL import Image import requests import urllib from keras_retinanet.utils.visualization import draw_box, draw_caption , label_color from keras_retinanet.utils.image import preprocess_image, resize_image
pngPath='C:/Users/PraveenKumar/RetinaNet//maskDetectorJPEGImages/' annotPath='C:/Users/PraveenKumar/RetinaNet//maskDetectorXMLfiles/' data=pd.DataFrame(columns=['fileName','xmin','ymin','xmax','ymax','class']) os.getcwd() ##读全部文件 allfiles = [f for f in listdir(annotPath) if isfile(join(annotPath, f))]
#读取全部pdf文件的图像,而后在文本存储在临时文件夹 for file in allfiles: #print(file) if (file.split(".")[1]=='xml'): fileName='C:/Users/PraveenKumar/RetinaNet/maskDetectorJPEGImages/'+file.replace(".xml",'.jpg') tree = ET.parse(annotPath+file) root = tree.getroot() for obj in root.iter('object'): cls_name = obj.find('name').text xml_box = obj.find('bndbox') xmin = xml_box.find('xmin').text ymin = xml_box.find('ymin').text xmax = xml_box.find('xmax').text ymax = xml_box.find('ymax').text #经过添加字典在空数据框架中追加行 data = data.append({'fileName': fileName, 'xmin': xmin, 'ymin':ymin,'xmax':xmax,'ymax':ymax,'class':cls_name}, ignore_index=True) data.shape
# 随机选取图像 filepath = df.sample()['fileName'].values[0] # 获取此图像的全部行 df2 = df[df['fileName'] == filepath] im = np.array(Image.open(filepath)) # 若是有PNG的话,它会有alpha通道 im = im[:,:,:3] for idx, row in df2.iterrows(): box = [ row['xmin'], row['ymin'], row['xmax'], row['ymax'], ] print(box) draw_box(im, box, color=(255, 0, 0)) plt.axis('off') plt.imshow(im) plt.show() show_image_with_boxes(data)
#检查少许数据记录 data.head()
#定义标签并将其写入文件 classes = ['mask','noMask'] with open('../maskDetectorClasses.csv', 'w') as f: for i, class_name in enumerate(classes): f.write(f'{class_name},{i}\n') if not os.path.exists('snapshots'): os.mkdir('snapshots')
注意:最好从一个预训练过的模型开始,而不是从头开始训练模型。咱们将使用已经在Coco数据集上预训练过的ResNet50模型。
URL_MODEL = 'https://github.com/fizyr/keras-retinanet/releases/download/0.5.1/resnet50_coco_best_v2.1.0.h5' urllib.request.urlretrieve(URL_MODEL, PRETRAINED_MODEL)
注意:若是你使用google colab,你可使用下面的代码片断来训练你的模型。
#把你的训练数据路径和文件放在训练数据的标签上 !keras_retinanet/bin/train.py --freeze-backbone \ --random-transform \ --weights {PRETRAINED_MODEL} \ --batch-size 8 \ --steps 500 \ --epochs 15 \ csv maskDetectorData.csv maskDetectorClasses.csv
但若你正在使用本地Jupyter Notebook或其余IDE进行训练,则能够在命令提示符下执行命令
python keras_retinanet/bin/train.py --freeze-backbone --random-transform \ --weights {PRETRAINED_MODEL} --batch-size 8 --steps 500 --epochs 15 csv maskDetectorData.csv maskDetectorClasses.csv
让咱们分析一下train.py的每一个参数.
from glob import glob model_paths = glob('snapshots/resnet50_csv_0*.h5') latest_path = sorted(model_paths)[-1] print("path:", latest_path) from keras_retinanet import models model = models.load_model(latest_path, backbone_name='resnet50') model = models.convert_model(model) label_map = {} for line in open('../maskDetectorClasses.csv'): row = line.rstrip().split(',') label_map[int(row[1])] = row[0]
#写一个函数,从你的数据集中随机选择一个图像,并预测使用训练模型。 def show_image_with_predictions(df, threshold=0.6): # 随机选择一个图像 row = df.sample() filepath = row['fileName'].values[0] print("filepath:", filepath) # 获取此图像的全部行 df2 = df[df['fileName'] == filepath] im = np.array(Image.open(filepath)) print("im.shape:", im.shape) # 若是有一个PNG,它会有alpha通道 im = im[:,:,:3] # 画出真实盒子 for idx, row in df2.iterrows(): box = [ row['xmin'], row['ymin'], row['xmax'], row['ymax'], ] print(box) draw_box(im, box, color=(255, 0, 0)) ### 画出预测 ### # 获取预测 imp = preprocess_image(im) imp, scale = resize_image(im) boxes, scores, labels = model.predict_on_batch( np.expand_dims(imp, axis=0) ) # 标准化框坐标 boxes /= scale # 循环获得每一个预测 for box, score, label in zip(boxes[0], scores[0], labels[0]): # 分数是排序的,因此一旦咱们看到分数低于阈值,咱们就能够退出 if score < threshold: break box = box.astype(np.int32) color = label_color(label) draw_box(im, box, color=color) class_name = label_map caption = f"{class_name} {score:.3f}" draw_caption(im, box, caption) score, label=score, label plt.axis('off') plt.imshow(im) plt.show() return score, label plt.rcParams['figure.figsize'] = [20, 10]
#能够根据你的业务需求随意更改阈值 label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 score, label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 score, label=show_image_with_predictions(data, threshold=0.6)
#能够根据你的业务需求随意更改阈值 score, label=show_image_with_predictions(data, threshold=0.6)
总而言之,咱们完成了使用RetinaNet制做口罩检测器的整个过程。 咱们建立了一个数据集,训练了一个模型并进行了测试(这是个人Notebook和数据集的Github存储库):https://github.com/Praveen76/...
RetinaNet是一个功能强大的模型,使用Feature Pyramid Networks&ResNet做为其骨干。 我可以经过很是有限的数据集和极少的迭代(每一个迭代有500个步长,共6次迭代)得到口罩检测器的良好结果。固然你也能够更改阈值。
注意:
通常来讲,RetinaNet是开始目标检测项目的一个很好的选择,特别是若是你须要快速得到良好的结果。
原文连接:https://www.analyticsvidhya.c...
欢迎关注磐创AI博客站:
http://panchuang.net/
sklearn机器学习中文官方文档:
http://sklearn123.com/
欢迎关注磐创博客资源汇总站:
http://docs.panchuang.net/