做者|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/