0
本文作者: AI研習(xí)社-譯站 | 2020-09-03 12:34 |
字幕組雙語原文:如何使用RetinaNet模型構(gòu)建面罩檢測器
英語原文:How to build a Face Mask Detector using RetinaNet Model!
翻譯:雷鋒字幕組(李珺毅)
目標(biāo)檢測是計算機(jī)視覺中一個非常重要的領(lǐng)域,對于自動駕駛、視頻監(jiān)控、醫(yī)療應(yīng)用和許多其他領(lǐng)域都是十分必要的。
我們正在努力應(yīng)對一場規(guī)??涨暗拇罅餍?。全球各地的研究人員都在瘋狂地嘗試開發(fā)COVID-19的疫苗或治療方法,而醫(yī)生們正努力防止這一流行病席卷整個世界。另一方面,許多國家發(fā)現(xiàn)了社交距離,戴口罩和手套是稍微抑制這種情況的一種方法。
最近我有了一個想法,用我的深度學(xué)習(xí)知識來幫助一下現(xiàn)在的情況。在本文中,我將向您介紹RetinaNet的實(shí)現(xiàn),而不需要什么背景知識和相關(guān)工作。
最重要的是什么?我們將使用RetinaNet建立一個口罩探測器來幫助我們應(yīng)對這一持續(xù)的流行病。您可以推斷相同的想法,為你的智能家居構(gòu)建一個啟用ai的解決方案。這個人工智能解決方案將只對戴著口罩和手套的開啟大樓的大門。
隨著無人機(jī)的成本隨著時間的推移而降低,我們看到了航拍數(shù)據(jù)的激增。因此,您可以使用這個RetinaNet模型在航空圖像甚至衛(wèi)星圖像中檢測不同的對象,如汽車(自行車、汽車等)或行人,以解決不同的業(yè)務(wù)問題。
所以,你可以看到對象檢測模型的應(yīng)用是無窮無盡的。
1.RetinaNet是什么
2.RetinaNet的需求
3.RetinaNet網(wǎng)絡(luò)結(jié)構(gòu)
-1.主干網(wǎng)絡(luò)
-2.目標(biāo)分類自網(wǎng)絡(luò)
-3.目標(biāo)回歸自網(wǎng)絡(luò)
4.Focal loss 損失函數(shù)
5.使用RetianNet模型建立口罩檢測器
-1.獲取數(shù)據(jù)
-2.建立數(shù)據(jù)集
-3.模型訓(xùn)練
-4.模型測試
6.備注
RetinaNet是最好的單階段目標(biāo)檢測模型之一,它已被證明可以很好地處理密集和小規(guī)模的物體。因此,它已成為我們在航空和衛(wèi)星圖像中使用的流行目標(biāo)檢測模型。
RetinaNet是由Facebook AI研究公司引入來解決密集檢測問題的。在處理極端的前景-背景類時,需要用它來彌補(bǔ)YOLO和SSD等單鏡頭對象檢測器的不平衡和不一致性。
從本質(zhì)上講,RetinaNet是由以下基本分組成的:
1.主干網(wǎng)絡(luò)(自下而上的邊路和具有側(cè)連接的自上而下的路徑)
2.目標(biāo)分類子網(wǎng)絡(luò)
3.目標(biāo)回歸子網(wǎng)絡(luò)
為了更好地理解,讓我們分別理解架構(gòu)的每個組件
1.自底向上路徑:自底向上路徑(例如,ResNet)用于特征提取。因此,它計算不同比例的特征地圖,而不考慮輸入圖像的大小。
2.具有橫向連接的自頂向下路徑:自頂向下路徑從更高的金字塔層次上采 樣空間上較粗糙的特征圖,橫向連接將具有相同空間大小的自頂向下和自底向上的層合并在一起。較高層次的特征圖往往具有較小的分辨率,但語義上更強(qiáng)。因此,更適合于檢測較大的物體; 相反,來自較低級特征圖的網(wǎng)格單元具有高分辨率,因此更擅長檢測較小的對象(參見圖64)。 因此,通過自上而下的路徑及其與路徑的自下而上的橫向連接的組合,這些操作不需要太多額外的計算,因此生成的特征圖的每個級別在語義和空間上都可以很強(qiáng)。 因此,該體系結(jié)構(gòu)是規(guī)模不變的,并且可以在速度和準(zhǔn)確性方面提供更好的性能。
每個FPN層都附加一個全卷積網(wǎng)絡(luò)(FCN)進(jìn)行對象分類。如圖所示,該子網(wǎng)包含3*3個卷積層,256個濾波器,然后是3*3個卷積層,K*A濾波器,因此輸出的feature map大小為W*H*KA,其中W和H與輸入特征圖的寬度和高度成比例,K和A分別為對象類和錨盒的數(shù)量。
最后采用Sigmoid層(不是softmax層)進(jìn)行對象分類。
而最后一個卷積層之所以有KA濾波器是因?yàn)椋绻麖淖詈笠粋€卷積層得到的feature map中的每個位置都有很多錨盒候選區(qū)域,那么每個錨盒都有可能被分類為K個類。所以輸出的特征圖大小將是KA通道或過濾器。
回歸子網(wǎng)絡(luò)與分類子網(wǎng)絡(luò)并行附著在FPN的每個特征圖上?;貧w子網(wǎng)絡(luò)的設(shè)計與分類子網(wǎng)絡(luò)相同,只是最后一個卷積層大小為3*3,有4個filter,輸出的feature map大小為W*H*4A。
最后一個卷積層有4個過濾器的原因是,為了定位類對象,回歸子網(wǎng)絡(luò)為每個錨定盒產(chǎn)生4個數(shù)字,這些數(shù)字預(yù)測錨定盒和真實(shí)框錨盒之間的相對偏移量(根據(jù)中心坐標(biāo)、寬度和高度)。因此,回歸子網(wǎng)的輸出特征圖具有4A濾波器或通道。
Focal Loss(FL)是Cross-Entropy Loss(CE)的改進(jìn)版本,它通過為困難的或容易錯誤分類的示例(即具有嘈雜紋理或部分對象或我們感興趣的對象的背景)分配更多權(quán)重來嘗試處理類不平衡問題 ,并簡化簡單的示例(即背景對象)。
因此,“Focal Loss”減少了簡單示例帶來的損失貢獻(xiàn),并提高了糾正錯誤分類的示例的重要性。 焦點(diǎn)損失只是交叉熵?fù)p失函數(shù)的擴(kuò)展,它將降低簡單示例的權(quán)重,并將訓(xùn)練重點(diǎn)放在困難樣本上。
所以為了實(shí)現(xiàn)這些研究人員提出了-
1- pt代表交叉熵?fù)p失,可調(diào)聚焦參數(shù)≥0。 RetinaNet物體檢測方法使用焦距損失的α平衡變體,其中α= 0.25,γ= 2效果最佳。
所以focal loss 的定義是:
對于γ∈[0,5]的幾個值,可以看到Focal Loss,請參見圖1。我們將注意到聚焦損耗的以下特性:
1.當(dāng)示例分類錯誤且pt小時,調(diào)制因子接近1并且不影響損失。
2.當(dāng)pt→1時,因子變?yōu)?,并且可以很好地權(quán)衡分類良好的示例的損失。
3.Focal loss γ平滑地調(diào)整了簡單示例的權(quán)重。 隨著γ的增加,調(diào)制因子的 作用也同樣增加。 (經(jīng)過大量實(shí)驗(yàn)和試驗(yàn),研究人員發(fā)現(xiàn)γ= 2最有效)
注意:-當(dāng)FL = 0時,F(xiàn)L等于CE。如圖藍(lán)色曲線所示
直觀地看,調(diào)制因子減小了簡單例的損耗貢獻(xiàn),擴(kuò)展了例的低損耗范圍。
你可以在這篇文章中讀到關(guān)于Focal loss的詳細(xì)信息(鏈接到我的focal loss文章),在這篇文章中我討論了交叉熵演變成focal loss,focal loss的需要,focal loss和交叉熵的比較
最重要的是,我用了幾個例子來解釋為什么focal loss比交叉熵好。
現(xiàn)在讓我們看看用Python實(shí)現(xiàn)RetinaNet來構(gòu)建口罩檢測器。
任何深度學(xué)習(xí)模型都需要大量的訓(xùn)練數(shù)據(jù)才能在測試數(shù)據(jù)上得到好的結(jié)果。在這篇文章中(鏈接到我的Web文章),我談到了為您的深度學(xué)習(xí)項(xiàng)目收集大量圖像的Web方法。
創(chuàng)建數(shù)據(jù)集
我們首先使用LabelImg工具為訓(xùn)練和驗(yàn)證數(shù)據(jù)集創(chuàng)建注釋。這個優(yōu)秀的注釋工具允許您快速注釋對象的邊框,以訓(xùn)練機(jī)器學(xué)習(xí)模型。
您可以在anaconda命令提示符中使用下面的命令來安裝它
pip install labelImg |
您可以使用如下所示的labelmg工具對每個JPEG文件進(jìn)行注釋,它將生成帶有每個邊框坐標(biāo)的XML文件。我們將使用這些xml文件來訓(xùn)練我們的模型。
第一步:克隆安裝keras-retinaNet代碼倉庫
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') |
注意:最好從一個預(yù)先訓(xùn)練好的模型開始,而不是從頭開始訓(xùn)練一個模型。我們將使用已經(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,您可以使用下面的代碼片段來訓(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的每個參數(shù)。
1.freeze-backbone:凍結(jié)主干層,當(dāng)我們使用小數(shù)據(jù)集時特別有用,以避免過擬合
2.random-transform:隨機(jī)變換數(shù)據(jù)集以獲得數(shù)據(jù)增強(qiáng)
3.weights:使用一個預(yù)先訓(xùn)練好的模型(您自己的模型或者Fizyr發(fā)布的模型)初始化模型
4.batch-size:訓(xùn)練批量大小,值越高,學(xué)習(xí)曲線越平滑
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制作面罩檢測器的整個過程。 我們創(chuàng)建了一個數(shù)據(jù)集,訓(xùn)練了一個模型并進(jìn)行了測試(這是我的筆記本和數(shù)據(jù)集的Github存儲庫)。
Retina Net是一個功能強(qiáng)大的模型,使用Feature Pyramid Networks&ResNet作為其骨干。 我能夠通過非常有限的數(shù)據(jù)集和極少的迭代(每個迭代有500個步長,共6次迭代)獲得口罩檢測器的良好結(jié)果。當(dāng)然你也可以更改閾值。
1.確保你訓(xùn)練你的模型至少20次迭代,以獲得好的結(jié)果。
2.一個好的想法是提交使用RetinaNet模型構(gòu)建口罩檢測器的方法。 人們總是可以根據(jù)業(yè)務(wù)需求調(diào)整模型,數(shù)據(jù)和方法。
一般來說,RetinaNet是開始目標(biāo)檢測項(xiàng)目的一個很好的選擇,特別是如果您需要快速獲得良好的結(jié)果。
雷鋒字幕組是一個由 AI 愛好者組成的翻譯團(tuán)隊,匯聚五百多位志愿者的力量,分享最新的海外AI資訊,交流關(guān)于人工智能技術(shù)領(lǐng)域的行業(yè)變革與技術(shù)創(chuàng)新的見解。
團(tuán)隊成員有大數(shù)據(jù)專家、算法工程師、圖像處理工程師、產(chǎn)品經(jīng)理、產(chǎn)品運(yùn)營、IT咨詢?nèi)恕⒃谛熒?;志愿者們來自IBM、AVL、Adobe、阿里、百度等知名企業(yè),北大、清華、港大、中科院、南卡羅萊納大學(xué)、早稻田大學(xué)等海內(nèi)外高校研究所。
如果,你也是位熱愛分享的AI愛好者。歡迎與雷鋒字幕組一起,學(xué)習(xí)新知,分享成長。
雷鋒網(wǎng)雷鋒網(wǎng)
雷峰網(wǎng)版權(quán)文章,未經(jīng)授權(quán)禁止轉(zhuǎn)載。詳情見轉(zhuǎn)載須知。