0
本文作者: AI研習(xí)社-譯站 | 2020-09-03 12:34 |
字幕組雙語(yǔ)原文:如何使用RetinaNet模型構(gòu)建面罩檢測(cè)器
英語(yǔ)原文:How to build a Face Mask Detector using RetinaNet Model!
翻譯:雷鋒字幕組(李珺毅)
目標(biāo)檢測(cè)是計(jì)算機(jī)視覺(jué)中一個(gè)非常重要的領(lǐng)域,對(duì)于自動(dòng)駕駛、視頻監(jiān)控、醫(yī)療應(yīng)用和許多其他領(lǐng)域都是十分必要的。
我們正在努力應(yīng)對(duì)一場(chǎng)規(guī)模空前的大流行。全球各地的研究人員都在瘋狂地嘗試開(kāi)發(fā)COVID-19的疫苗或治療方法,而醫(yī)生們正努力防止這一流行病席卷整個(gè)世界。另一方面,許多國(guó)家發(fā)現(xiàn)了社交距離,戴口罩和手套是稍微抑制這種情況的一種方法。
最近我有了一個(gè)想法,用我的深度學(xué)習(xí)知識(shí)來(lái)幫助一下現(xiàn)在的情況。在本文中,我將向您介紹RetinaNet的實(shí)現(xiàn),而不需要什么背景知識(shí)和相關(guān)工作。
最重要的是什么?我們將使用RetinaNet建立一個(gè)口罩探測(cè)器來(lái)幫助我們應(yīng)對(duì)這一持續(xù)的流行病。您可以推斷相同的想法,為你的智能家居構(gòu)建一個(gè)啟用ai的解決方案。這個(gè)人工智能解決方案將只對(duì)戴著口罩和手套的開(kāi)啟大樓的大門(mén)。
隨著無(wú)人機(jī)的成本隨著時(shí)間的推移而降低,我們看到了航拍數(shù)據(jù)的激增。因此,您可以使用這個(gè)RetinaNet模型在航空?qǐng)D像甚至衛(wèi)星圖像中檢測(cè)不同的對(duì)象,如汽車(chē)(自行車(chē)、汽車(chē)等)或行人,以解決不同的業(yè)務(wù)問(wèn)題。
所以,你可以看到對(duì)象檢測(cè)模型的應(yīng)用是無(wú)窮無(wú)盡的。
1.RetinaNet是什么
2.RetinaNet的需求
3.RetinaNet網(wǎng)絡(luò)結(jié)構(gòu)
-1.主干網(wǎng)絡(luò)
-2.目標(biāo)分類(lèi)自網(wǎng)絡(luò)
-3.目標(biāo)回歸自網(wǎng)絡(luò)
4.Focal loss 損失函數(shù)
5.使用RetianNet模型建立口罩檢測(cè)器
-1.獲取數(shù)據(jù)
-2.建立數(shù)據(jù)集
-3.模型訓(xùn)練
-4.模型測(cè)試
6.備注
RetinaNet是最好的單階段目標(biāo)檢測(cè)模型之一,它已被證明可以很好地處理密集和小規(guī)模的物體。因此,它已成為我們?cè)诤娇蘸托l(wèi)星圖像中使用的流行目標(biāo)檢測(cè)模型。
RetinaNet是由Facebook AI研究公司引入來(lái)解決密集檢測(cè)問(wèn)題的。在處理極端的前景-背景類(lèi)時(shí),需要用它來(lái)彌補(bǔ)YOLO和SSD等單鏡頭對(duì)象檢測(cè)器的不平衡和不一致性。
從本質(zhì)上講,RetinaNet是由以下基本分組成的:
1.主干網(wǎng)絡(luò)(自下而上的邊路和具有側(cè)連接的自上而下的路徑)
2.目標(biāo)分類(lèi)子網(wǎng)絡(luò)
3.目標(biāo)回歸子網(wǎng)絡(luò)
為了更好地理解,讓我們分別理解架構(gòu)的每個(gè)組件
1.自底向上路徑:自底向上路徑(例如,ResNet)用于特征提取。因此,它計(jì)算不同比例的特征地圖,而不考慮輸入圖像的大小。
2.具有橫向連接的自頂向下路徑:自頂向下路徑從更高的金字塔層次上采 樣空間上較粗糙的特征圖,橫向連接將具有相同空間大小的自頂向下和自底向上的層合并在一起。較高層次的特征圖往往具有較小的分辨率,但語(yǔ)義上更強(qiáng)。因此,更適合于檢測(cè)較大的物體; 相反,來(lái)自較低級(jí)特征圖的網(wǎng)格單元具有高分辨率,因此更擅長(zhǎng)檢測(cè)較小的對(duì)象(參見(jiàn)圖64)。 因此,通過(guò)自上而下的路徑及其與路徑的自下而上的橫向連接的組合,這些操作不需要太多額外的計(jì)算,因此生成的特征圖的每個(gè)級(jí)別在語(yǔ)義和空間上都可以很強(qiáng)。 因此,該體系結(jié)構(gòu)是規(guī)模不變的,并且可以在速度和準(zhǔn)確性方面提供更好的性能。
每個(gè)FPN層都附加一個(gè)全卷積網(wǎng)絡(luò)(FCN)進(jìn)行對(duì)象分類(lèi)。如圖所示,該子網(wǎng)包含3*3個(gè)卷積層,256個(gè)濾波器,然后是3*3個(gè)卷積層,K*A濾波器,因此輸出的feature map大小為W*H*KA,其中W和H與輸入特征圖的寬度和高度成比例,K和A分別為對(duì)象類(lèi)和錨盒的數(shù)量。
最后采用Sigmoid層(不是softmax層)進(jìn)行對(duì)象分類(lèi)。
而最后一個(gè)卷積層之所以有KA濾波器是因?yàn)?,如果從最后一個(gè)卷積層得到的feature map中的每個(gè)位置都有很多錨盒候選區(qū)域,那么每個(gè)錨盒都有可能被分類(lèi)為K個(gè)類(lèi)。所以輸出的特征圖大小將是KA通道或過(guò)濾器。
回歸子網(wǎng)絡(luò)與分類(lèi)子網(wǎng)絡(luò)并行附著在FPN的每個(gè)特征圖上?;貧w子網(wǎng)絡(luò)的設(shè)計(jì)與分類(lèi)子網(wǎng)絡(luò)相同,只是最后一個(gè)卷積層大小為3*3,有4個(gè)filter,輸出的feature map大小為W*H*4A。
最后一個(gè)卷積層有4個(gè)過(guò)濾器的原因是,為了定位類(lèi)對(duì)象,回歸子網(wǎng)絡(luò)為每個(gè)錨定盒產(chǎn)生4個(gè)數(shù)字,這些數(shù)字預(yù)測(cè)錨定盒和真實(shí)框錨盒之間的相對(duì)偏移量(根據(jù)中心坐標(biāo)、寬度和高度)。因此,回歸子網(wǎng)的輸出特征圖具有4A濾波器或通道。
Focal Loss(FL)是Cross-Entropy Loss(CE)的改進(jìn)版本,它通過(guò)為困難的或容易錯(cuò)誤分類(lèi)的示例(即具有嘈雜紋理或部分對(duì)象或我們感興趣的對(duì)象的背景)分配更多權(quán)重來(lái)嘗試處理類(lèi)不平衡問(wèn)題 ,并簡(jiǎn)化簡(jiǎn)單的示例(即背景對(duì)象)。
因此,“Focal Loss”減少了簡(jiǎn)單示例帶來(lái)的損失貢獻(xiàn),并提高了糾正錯(cuò)誤分類(lèi)的示例的重要性。 焦點(diǎn)損失只是交叉熵?fù)p失函數(shù)的擴(kuò)展,它將降低簡(jiǎn)單示例的權(quán)重,并將訓(xùn)練重點(diǎn)放在困難樣本上。
所以為了實(shí)現(xiàn)這些研究人員提出了-
1- pt代表交叉熵?fù)p失,可調(diào)聚焦參數(shù)≥0。 RetinaNet物體檢測(cè)方法使用焦距損失的α平衡變體,其中α= 0.25,γ= 2效果最佳。
所以focal loss 的定義是:
對(duì)于γ∈[0,5]的幾個(gè)值,可以看到Focal Loss,請(qǐng)參見(jiàn)圖1。我們將注意到聚焦損耗的以下特性:
1.當(dāng)示例分類(lèi)錯(cuò)誤且pt小時(shí),調(diào)制因子接近1并且不影響損失。
2.當(dāng)pt→1時(shí),因子變?yōu)?,并且可以很好地權(quán)衡分類(lèi)良好的示例的損失。
3.Focal loss γ平滑地調(diào)整了簡(jiǎn)單示例的權(quán)重。 隨著γ的增加,調(diào)制因子的 作用也同樣增加。 (經(jīng)過(guò)大量實(shí)驗(yàn)和試驗(yàn),研究人員發(fā)現(xiàn)γ= 2最有效)
注意:-當(dāng)FL = 0時(shí),F(xiàn)L等于CE。如圖藍(lán)色曲線(xiàn)所示
直觀地看,調(diào)制因子減小了簡(jiǎn)單例的損耗貢獻(xiàn),擴(kuò)展了例的低損耗范圍。
你可以在這篇文章中讀到關(guān)于Focal loss的詳細(xì)信息(鏈接到我的focal loss文章),在這篇文章中我討論了交叉熵演變成focal loss,focal loss的需要,focal loss和交叉熵的比較
最重要的是,我用了幾個(gè)例子來(lái)解釋為什么focal loss比交叉熵好。
現(xiàn)在讓我們看看用Python實(shí)現(xiàn)RetinaNet來(lái)構(gòu)建口罩檢測(cè)器。
任何深度學(xué)習(xí)模型都需要大量的訓(xùn)練數(shù)據(jù)才能在測(cè)試數(shù)據(jù)上得到好的結(jié)果。在這篇文章中(鏈接到我的Web文章),我談到了為您的深度學(xué)習(xí)項(xiàng)目收集大量圖像的Web方法。
創(chuàng)建數(shù)據(jù)集
我們首先使用LabelImg工具為訓(xùn)練和驗(yàn)證數(shù)據(jù)集創(chuàng)建注釋。這個(gè)優(yōu)秀的注釋工具允許您快速注釋對(duì)象的邊框,以訓(xùn)練機(jī)器學(xué)習(xí)模型。
您可以在anaconda命令提示符中使用下面的命令來(lái)安裝它
pip install labelImg |
您可以使用如下所示的labelmg工具對(duì)每個(gè)JPEG文件進(jìn)行注釋?zhuān)鼘⑸蓭в忻總€(gè)邊框坐標(biāo)的XML文件。我們將使用這些xml文件來(lái)訓(xùn)練我們的模型。
第一步:克隆安裝keras-retinaNet代碼倉(cāng)庫(kù)
import osprint(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()#read All filesallfiles = [f for f in listdir(annotPath) if isfile(join(annotPath, f)) |
#Read all pdf files in images and then in text and store that in temp folder #Read all pdf files in images and then in text and store that in temp folder 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 # Append rows in Empty Dataframe by adding dictionaries data = data.append({'fileName': fileName, 'xmin': xmin, 'ymin':ymin,'xmax':xmax,'ymax':ymax,'class':cls_name}, ignore_index=True) |
# pick a random image filepath = df.sample()['fileName'].values[0]
# get all rows for this image df2 = df[df['fileName'] == filepath] im = np.array(Image.open(filepath))
# if there's a PNG it will have alpha channel 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) |
#Check few records of datadata.head( |
#Define labels & write them in a fileclasses = ['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') |
注意:最好從一個(gè)預(yù)先訓(xùn)練好的模型開(kāi)始,而不是從頭開(kāi)始訓(xùn)練一個(gè)模型。我們將使用已經(jīng)在Coco數(shù)據(jù)集上預(yù)先訓(xùn)練好的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) |
注意:如果您正在使用谷歌Colab,您可以使用下面的代碼片段來(lái)訓(xùn)練您的模型。
#Put your training data path & file that has labels for your training data!keras_retinanet/bin/train.py --freeze-backbone \ --random-transform \ --weights {PRETRAINED_MODEL} \ --batch-size 8 \ --steps 500 \ --epochs 15 \ csv maskDetectorData.csv maskDetectorClasses.csv |
但如果你重新訓(xùn)練你的本地Jupyter Notebook或不同的IDE訓(xùn)練,然后你可以從命令提示符下面的命令
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的每個(gè)參數(shù)。
1.freeze-backbone:凍結(jié)主干層,當(dāng)我們使用小數(shù)據(jù)集時(shí)特別有用,以避免過(guò)擬合
2.random-transform:隨機(jī)變換數(shù)據(jù)集以獲得數(shù)據(jù)增強(qiáng)
3.weights:使用一個(gè)預(yù)先訓(xùn)練好的模型(您自己的模型或者Fizyr發(fā)布的模型)初始化模型
4.batch-size:訓(xùn)練批量大小,值越高,學(xué)習(xí)曲線(xiàn)越平滑
5.step:迭代的步數(shù)
6.epochs:迭代的次數(shù)
7.csv:上面的腳本生成的注釋文件
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] |
#Write a function to choose one image randomly from your dataset and predict using Trained model.def show_image_with_predictions(df, threshold=0.6): # choose a random image row = df.sample() filepath = row['fileName'].values[0] print("filepath:", filepath) # get all rows for this image df2 = df[df['fileName'] == filepath] im = np.array(Image.open(filepath)) print("im.shape:", im.shape)
# if there's a PNG it will have alpha channel im = im[:,:,:3]
# plot true boxes 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))
### plot predictions ### # get predictions imp = preprocess_image(im) imp, scale = resize_image(im)
boxes, scores, labels = model.predict_on_batch( np.expand_dims(imp, axis=0) )
# standardize box coordinates boxes /= scale
# loop through each prediction for the input image for box, score, label in zip(boxes[0], scores[0], labels[0]): # scores are sorted so we can quit as soon # as we see a score below threshold 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] |
#Feel free to change threshold as per your business requirement score, label=show_image_with_predictions(data, threshold=0.6) |
http://arxiv.org/abs/1605.06409.
https://arxiv.org/pdf/1708.02002.pdf
https://developers.arcgis.com/python/guide/how-retinanet-works/
https://analyticsindiamag.com/what-is-retinanet-ssd-focal-loss/
https://github.com/fizyr/keras-retinanet
https://www.freecodecamp.org/news/object-detection-in-colab-with-fizyr-retinanet-efed36ac4af3/
https://deeplearningcourses.com/
https://blog.zenggyu.com/en/post/2018-12-05/retinanet-explained-and-demystified/
總而言之,我們完成了使用RetinaNet制作面罩檢測(cè)器的整個(gè)過(guò)程。 我們創(chuàng)建了一個(gè)數(shù)據(jù)集,訓(xùn)練了一個(gè)模型并進(jìn)行了測(cè)試(這是我的筆記本和數(shù)據(jù)集的Github存儲(chǔ)庫(kù))。
Retina Net是一個(gè)功能強(qiáng)大的模型,使用Feature Pyramid Networks&ResNet作為其骨干。 我能夠通過(guò)非常有限的數(shù)據(jù)集和極少的迭代(每個(gè)迭代有500個(gè)步長(zhǎng),共6次迭代)獲得口罩檢測(cè)器的良好結(jié)果。當(dāng)然你也可以更改閾值。
1.確保你訓(xùn)練你的模型至少20次迭代,以獲得好的結(jié)果。
2.一個(gè)好的想法是提交使用RetinaNet模型構(gòu)建口罩檢測(cè)器的方法。 人們總是可以根據(jù)業(yè)務(wù)需求調(diào)整模型,數(shù)據(jù)和方法。
一般來(lái)說(shuō),RetinaNet是開(kāi)始目標(biāo)檢測(cè)項(xiàng)目的一個(gè)很好的選擇,特別是如果您需要快速獲得良好的結(jié)果。
雷鋒字幕組是一個(gè)由 AI 愛(ài)好者組成的翻譯團(tuán)隊(duì),匯聚五百多位志愿者的力量,分享最新的海外AI資訊,交流關(guān)于人工智能技術(shù)領(lǐng)域的行業(yè)變革與技術(shù)創(chuàng)新的見(jiàn)解。
團(tuán)隊(duì)成員有大數(shù)據(jù)專(zhuān)家、算法工程師、圖像處理工程師、產(chǎn)品經(jīng)理、產(chǎn)品運(yùn)營(yíng)、IT咨詢(xún)?nèi)恕⒃谛熒?;志愿者們?lái)自IBM、AVL、Adobe、阿里、百度等知名企業(yè),北大、清華、港大、中科院、南卡羅萊納大學(xué)、早稻田大學(xué)等海內(nèi)外高校研究所。
如果,你也是位熱愛(ài)分享的AI愛(ài)好者。歡迎與雷鋒字幕組一起,學(xué)習(xí)新知,分享成長(zhǎng)。
雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見(jiàn)轉(zhuǎn)載須知。