乐趣区

关于人工智能:使用RetinaNet构建的人脸口罩探测器

作者 |GUEST
编译 |VK
起源 |Analytics Vidhya

介绍

指标检测是计算机视觉中一个十分重要的畛域,对于主动驾驶、视频监控、医疗利用和许多其余畛域都是必要的。

咱们正在与一场规模空前的传染病作奋斗。全世界的钻研人员都在试图开发一种疫苗或医治 COVID-19 的办法,而医生们却在致力阻止这场传染病席卷全世界。另一方面,许多国家发现了社会间隔的疏远,应用口罩和手套能够略微遏制这种场面。

我最近有一个想法,用我的深度学习常识来帮忙目前的状况。在这篇文章中,我将向你介绍 RetinaNet 的实现,背景常识不多。

咱们将应用 RetinaNet 建设一个“口罩探测器”来帮忙咱们应答这场继续的传染病。你能够推断出同样的想法来为你的智能家居构建一个反对人工智能的解决方案。这个人工智能的解决方案只对戴着口罩和手套的人敞开大门。

随着无人机的老本随着工夫的推移而升高,咱们看到地面数据的生成呈现了一个大的峰值。因而,你能够应用这个 RetinaNet 模型在航空图像甚至卫星图像中检测不同的对象,如汽车 (自行车、汽车等) 或行人,以解决不同的业务问题。

所以,你看指标检测模型的利用是无穷无尽的。

目录

  1. 什么是 RetinaNet
  2. RetinaNet 的需要
  3. RetinaNet 的架构

    1. 骨干网
    2. 对象分类子网
    3. 对象回归子网
  4. Focal Loss
  5. 利用 RetinaNet 模型建设口罩检测器

    1. 收集数据
    2. 创立数据集
    3. 模特训练
    4. 模型测试
  6. 最初阐明

什么是 RetinaNet

RetinaNet 是一种最好的单指标检测模型,已被证实能很好地解决密集和小尺度的物体。因为这个起因,它曾经成为一个风行的指标检测模型。

RetinaNet 的需要

RetinaNet 是由 Facebook 人工智能研究所(Facebook-AI-Research)引入的,旨在解决密集检测问题。在解决极其前景 - 背景类时,须要补救 YOLO 和 SSD 等单步指标检测器的不均衡和不统一。

RetinaNet 的架构

从实质上讲,RetinaNet 是一个复合网络,由以下局部组成:

  1. 骨干网络(自底向上的门路和具备横向连贯的自上而下的门路)
  2. 指标分类子网
  3. 指标回归子网

为了更好地了解,让咱们别离理解架构的每个组件

1. 骨干网络

  1. 自底向上门路: 自底向上门路 (例如,ResNet) 用于特征提取。因而,它计算不同比例的特色图,而不思考输出图像的大小。
  2. 具备横向连贯的自上而下的门路:在自上而下的门路上,从更高的金字塔级别对空间上较毛糙的特色图进行上采样,横向连贯将具备雷同空间大小的自顶向下和自底向上的层合并在一起。较高层次的特色图往往具备较小的分辨率,但语义上更强。因而,更适宜于检测较大的物体;相同,来自较低级特色图的网格单元具备高分辨率,因而更善于检测较小的对象。因而,联合自上而下的门路及其与自底向上的门路的横向连贯,不须要太多额定的计算,因而生成的特色图的每个级别在语义和空间上都能够很强。因而,该体系结构是规模不变的,并且能够在速度和准确性方面提供更好的性能。

2. 指标分类子网

每个 FPN 层都附加一个全卷积网络 (FCN) 进行对象分类。如图所示,该子网蕴含 3 * 3 个卷积层,256 个滤波器,而后是 3 * 3 个卷积层,K* A 滤波器,因而输入的 feature map 大小为 W *H*KA,其中 W 和 H 与输出特色图的宽度和高度成比例,K 和 A 别离为对象类和锚盒的数量。

最初利用 Sigmoid 层(而不是 softmax)进行指标分类。

而最初一个卷积层之所以有 KA 滤波器是因为,如果从最初一个卷积层失去的特色图中的每个地位都有很多锚盒候选区域,那么每个锚盒都有可能被分类为 K 个类。所以输入的特色图大小将是 KA 通道或过滤器。

3. 指标回归子网

回归子网与分类子网并行附着在 FPN 的每个特色图上。回归子网的设计与分类子网雷同,只是最初一个卷积层大小为 3 *3,有 4 个 filter,输入的特色图大小为 W *H*4A。

最初一个卷积层有 4 个过滤器的起因是,为了定位类对象,回归子网络为每个锚定盒产生 4 个数字,这些数字预测锚定盒和实在框锚盒之间的绝对偏移量(依据核心坐标、宽度和高度)。因而,回归子网的输入特色图具备 4A 滤波器或通道。

Focal Loss

Focal Loss(FL)是 Cross-Entropy Loss(CE)的改良版本,它通过为艰难的或容易谬误分类的示例(即具备嘈杂纹理或局部对象或咱们感兴趣的对象的背景)调配更多权重来尝试解决类不均衡问题,并简化简略的示例(即背景对象)。

因而,“Focal Loss”缩小了简略示例带来的损失奉献,并进步了纠正错误分类的示例的重要性。焦点损失只是穿插熵损失函数的扩大,它将升高简略示例的权重,并将训练重点放在艰难样本上。

所以为了实现这些钻研人员提出了

1- pt 代表穿插熵损失,可调聚焦参数≥0。RetinaNet 物体检测办法应用焦距损失的 α 均衡变体,其中 α = 0.25,γ= 2 成果最佳。

所以 Focal Loss 能够定义为

请参见图,对于 γ∈[0,5]的几个值,咱们将留神到 Focal Loss 的以下个性:

  1. 当示例分类谬误且 pt 小时,调制因子靠近 1 并且不影响损失。
  2. 当 pt→1 时,因子变为 0,并且能够很好地衡量分类良好的示例的损失。
  3. Focal loss γ 平滑地调整了简略示例的权重。随着 γ 的减少,调制因子的作用也同样减少。(通过大量试验和试验,钻研人员发现 γ = 2 最无效)

:什么时候 γ =0,FL 相当于 CE。图中所示为蓝色曲线

直观地看,调制因子减小了简略例的损耗奉献,扩大了例的低损耗范畴。

当初让咱们看看用 Python 实现 RetinaNet 来构建口罩检测器。

利用 RetinaNet 模型建设口罩检测器

收集数据

任何深度学习模型都须要大量的训练数据能力在测试数据上产生良好的后果。

创立数据集

咱们开始应用 LabelImg 工具创立数据集和验证。这个优良的正文工具能够让你疾速地正文对象的边界框,从而训练机器学习模型。

你能够在 anaconda 命令提示符下应用上面的命令装置它

pip install labelImg

你能够应用上面的 labelmg 工具对每个 JPEG 文件进行正文,它将生成带有每个边界框坐标的 XML 文件。咱们将应用这些 xml 文件来训练咱们的模型。

模型训练

第 1 步:克隆并装置keras-retinanet
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
第 2 步:导入所有必要库
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
第 3 步:导入 JPEG 和 xml 数据
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
第 4 步:编写一个函数来显示训练数据集上的边界框
 # 随机选取图像
  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)
第 5 步:训练 RetinaNet 模型

留神:如果你应用 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 的每个参数.

  1. freeze-backbone: 解冻骨干层,当咱们应用小数据集时特地有用,以防止过拟合
  2. random-transform: 随机变换数据集以取得数据加强
  3. weights: 应用一个事后训练好的模型 (您本人的模型或者 Fizyr 公布的模型) 初始化模型
  4. batch-size: 训练批量大小,值越高,学习曲线越平滑
  5. step: 迭代的步数
  6. epochs: 迭代的次数
  7. csv: 下面的脚本生成的正文文件
第 6 步:载入训练模型
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]
模型测试:
第 7 步:利用训练模型进行预测
# 写一个函数,从你的数据集中随机抉择一个图像,并预测应用训练模型。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)

参考文献

  • http://arxiv.org/abs/1605.06409.
  • https://arxiv.org/pdf/1708.02…
  • https://developers.arcgis.com…
  • https://github.com/fizyr/kera…
  • https://www.freecodecamp.org/…
  • https://deeplearningcourses.com/
  • https://blog.zenggyu.com/en/p…

最初阐明

总而言之,咱们实现了应用 RetinaNet 制作口罩检测器的整个过程。咱们创立了一个数据集,训练了一个模型并进行了测试(这是我的 Notebook 和数据集的 Github 存储库):https://github.com/Praveen76/…

RetinaNet 是一个功能强大的模型,应用 Feature Pyramid Networks&ResNet 作为其骨干。我可能通过十分无限的数据集和极少的迭代(每个迭代有 500 个步长,共 6 次迭代)取得口罩检测器的良好后果。当然你也能够更改阈值。

留神:

  1. 确保你训练你的模型至多 20 次迭代,以取得好的后果。
  2. 一个好的想法是提交应用 RetinaNet 模型构建口罩检测器的办法。人们总是能够依据业务需要调整模型,数据和办法。

一般来说,RetinaNet 是开始指标检测我的项目的一个很好的抉择,特地是如果你须要疾速取得良好的后果。

原文链接:https://www.analyticsvidhya.c…

欢送关注磐创 AI 博客站:
http://panchuang.net/

sklearn 机器学习中文官网文档:
http://sklearn123.com/

欢送关注磐创博客资源汇总站:
http://docs.panchuang.net/

退出移动版