教程|用深度學習DIY自動化監控系統

選自Medium,作者:Bharath Raj,機器之心編譯,參與:Huiyuan Zhuo、張倩。

監控在安保和巡查中發揮著重要作用,但也是一項非常乏味的任務,深度學習的出現在一定程度上將人類從這一任務中解放出來。本文介紹瞭如何使用基於深度學習的目標檢測去搭建一個簡單但有效的監控系統,還比較了使用 GPU 多處理進行推斷的不同目標檢測模型在行人檢測方面的性能。

監控是安保和巡查一個不可或缺的組成部分。在大多數情況下,這項工作需要長時間去查找一些你不期望發生的事。我們做的這件事很重要,但也是一項非常乏味的任務。

如果有什麼東西可以代替我們做「觀察和等待」的工作,生活不就簡單多了嗎?嗯,你很幸運。憑藉過去幾年的技術進步,我們可以編寫一些腳本來自動執行上述任務—而且也很容易實現。但在我們深入探討之前,讓我們自問:機器的表現和人類一樣好嗎?

任何熟悉深度學習的人都知道圖像分類器的準確率已經超出了人類水平。

教程|用深度學習DIY自動化監控系統

傳統計算機視覺(CV)和深度學習相比於人類,在 ImageNet 數據集上隨時間變化的錯誤率。(圖源:https://www.dsiac.org/resources/journals/dsiac/winter-2017-volume-4-number-1/real-time-situ-intelligent-video-analytics)

與人類相比,機器可以以相同(或更好)的標準保持對物體的監控。因此使用技術去進行監控要高效得多。

  • 監控是一項重複且乏味的任務,可能會導致人類表現的下降。但使用技術進行監控,我們就可以在出現問題時專注於採取行動。
  • 為了去調查一大片區域,你會需要大量人力。而固定攝像機的視野範圍是有限的。通過使用移動監控機器人(比如微型無人機)可以減輕這些問題。

此外,同樣的技術還有除了安保以外的各種應用,比如嬰兒監視器或自動化產品交付。

好極了!但是我們如何實現自動化呢?

在設計複雜的理論之前,讓我們考慮一下監控的正常運作方式。如果看一段視頻時發現了異常,我們就會採取行動。所以從本質上說,我們的技術應該細讀視頻的每一幀,希望可以發現一些異常的東西。這個過程是不是很耳熟?

正如你可能已經猜到的那樣,這就是使用帶有定位的目標檢測的本質。它和分類略有不同,就是我們需要知道目標的確切位置。此外,我們可能在單張圖像中有多個目標。

教程|用深度學習DIY自動化監控系統

為了找到目標的確切位置,我們的算法應該檢查圖像的每一部分以找到一個類的存在。這比聽起來更難。但自 2014 年以來,深度學習領域不斷更新的研究已經引入了可以實時檢測目標的複雜神經網絡。

教程|用深度學習DIY自動化監控系統

看,僅在 2 年時間內,性能就增加了那麼多!

有幾種在內部使用不同方法的深度學習架構來實現相同的任務。最流行的變種是 Faster RCNN、YOLO 和 SSD 網絡。

教程|用深度學習DIY自動化監控系統

速度和準確率的權衡。更高的 mAP 和 更少的 GPU 運行時間是最優的。

每個模型都依賴於一個基礎分類器,該分類器對最終的準確率和模型大小有很大影響。此外,目標檢測器的選擇會極大影響計算複雜度和最終準確率。

選擇目標檢測算法的過程通常是速度、準確率和模型大小之間的權衡。

在本博文中,我們將學習如何使用目標檢測搭建一個簡單但有效的監控系統。讓我們先討論一下由於監控任務的性質而受限制的約束。

深度學習在監控領域的限制因素

我們經常想持續關注一大片區域的情況。在實現自動化監控前,我們需要考慮一些因素。

1. 視頻輸入

一般來說,為了監控一大片區域,我們需要多個攝像機。此外,這些攝像機需要在某個地方存儲數據;要麼在本地,要麼在某個遠程存儲。

教程|用深度學習DIY自動化監控系統

典型的監控攝像機。(圖片來自 Unsplash 的 Scott Webb)

較高質量的視頻將比較低質量的視頻佔用更多的內存。此外,RGB 輸入流比 BW 輸入流大 3 倍。由於我們只能存儲有限數量的輸入流,因此通常會降低質量以最大化存儲。

因此,可擴展的監控系統應該能夠解析低質量的圖像。因此,我們的深度學習算法也必須在低質量的圖像上進行訓練。

2. 處理能力

現在已經解決了輸入約束,我們可以去回答一個更大的問題。我們在哪裡處理從攝像機中獲得的數據?有兩種方法可以做到這一點。

  • 在中央服務器上處理:

來自攝像機的視頻流在遠程服務器或集群上逐幀處理。這個方法非常穩健,同時讓我們得以利用高準確率的複雜模型的優勢。顯而易見的問題是延遲;所以你需要一個快速的網絡連接來解決延遲。此外,如果你沒有使用商用 API,那麼服務器設置和維護的成本會很高。

教程|用深度學習DIY自動化監控系統

內存消耗與 GPU 推斷時間(毫秒)。大多數高性能模型都會消耗大量內存。(圖源:https://arxiv.org/pdf/1611.10012.pdf)

  • 邊緣處理

通過連接小型微控制器,我們可以在攝像機上進行實時推斷。這就沒有傳輸延遲,同時相比之前的方法,可以更快地報告異常。此外,對於移動機器人來說,這是一個很好的補充,因此它們不需要再受到可用的 WiFi / Bluetooth 範圍的限制。(比如微型無人機。)

教程|用深度學習DIY自動化監控系統

不同目標檢測器的 FPS 性能。(圖源:https://medium.com/@jonathan_hui/object-detection-speed-and-accuracy-comparison-faster-r-cnn-r-fcn-ssd-and-yolo-5425656ae359)

缺點是,微控制器沒有 GPU 那麼強大,因此你可能被迫使用較低準確率的模型。使用板載的 GPU 可以避免這個問題,但代價高昂。一個有趣的解決方案是使用像 TensorRT 這樣的軟件,此類軟件可以優化程序的推理過程。

訓練監控系統

在本節中,我們將使用目標檢測來檢測一下如何識別行人。我們將使用 TensorFlow 目標檢測 API 來構建我們的模塊。我們會簡要探討如何設置 API,並訓練其完成監控任務。詳細解釋見另一篇博文(https://medium.freecodecamp.org/how-to-play-quidditch-using-the-tensorflow-object-detection-api-b0742b99065d)。

整個過程可以被歸納為 3 個階段:

1. 數據準備

2. 訓練模型

3. 推斷

教程|用深度學習DIY自動化監控系統

涉及訓練目標檢測模型的工作流程。

如果你想看到那些能激勵你進行更多嘗試的結果,請向下滾動到第 3 階段!

階段 1:數據準備

步驟 1:獲取數據集

過去拍攝的監控錄像可能是你可以獲得的最準確的數據集。但是,大部分情況下,通常很難獲得這樣的監控錄像。在這種情況下,我們可以訓練自己的目標檢測器,以便從正常圖像中識別我們的目標。

教程|用深度學習DIY自動化監控系統

從我們的數據集中提取帶註釋的圖像。

如前所述,攝像機中的圖像質量可能較低。因此你必須訓練你的模型適應這樣的工作條件。一種巧妙的方法是使用數據擴充,在此有詳細解釋(https://medium.com/nanonets/how-to-use-deep-learning-when-you-have-limited-data-part-2-data-augmentation-c26971dc8ced)。本質上說,我們必須添加一些噪音來降低數據集中圖片的質量。我們還可以嘗試模糊和侵蝕效果。

為了目標檢測任務,我們將使用 TownCentre 數據集。我們將使用視頻的前 3600 幀進行訓練和驗證,剩下的 900 幀用來測試。你可以使用我 github repo 中的腳本來提取數據集。GitHub repo:https://github.com/thatbrguy/Pedestrian-Detector。

步驟 2:註釋數據集

你可以使用像 LabelImg 這樣的工具來進行註釋。這是一項乏味的任務,但同樣重要。註釋存儲為 XML 文件。

幸運的是,TownCentre 數據集的所有者提供了 csv 格式的註釋。我寫了一個快速腳本去將註釋轉化為需要的 XML 格式,同樣可以在上述 github repo 中找到。

步驟 3:克隆存儲庫

克隆存儲庫(https://github.com/thatbrguy/Pedestrian-Detector)。運行以下命令去安裝需求包,編譯一些 Protobuf 庫並設置路徑變量。

pip install -r requirements.txt
sudo apt-get install protobuf-compiler
protoc object_detection/protos/*.proto --python_out=.
export PYTHONPATH=$PYTHONPATH:`pwd`:`pwd`/slim

步驟 4:準備支持的輸入

我們需要給我們的目標分配一個 ID。我們在名為 label_map.pbtxt 的文件中定義 ID,如下所示:

item {
id: 1
name: ‘target’
}

接著,你必須創建一個包含 XML 和圖片文件名的文本文件。例如,如果你的數據集中有圖像 img1.jpg、img2.jpg 以及 img1.xml、img2.xml,你的 trainval.txt 應如下所示:

img1
img2

將你的數據集分成兩個文件夾,即 images 和 annotations。將 label_map.pbtxt 和 trainval.txt 放到 annotations 文件夾中。在 annotations 文件夾中創建一個名為 xmls 的文件夾,並將所有 XML 文件放入其中。你的目錄層次結構應如下所示:

-base_directory
|-images
|-annotations
||-xmls
||-label_map.pbtxt
||-trainval.txt

步驟 5:創建 TF Records

API 接受 TFRecords 文件格式的輸入。使用我的 repo 中提供的 create_tf_records.py 文件去將你的數據集轉換為 TFRecords。你應該在你的基本目錄執行以下命令:

python create_tf_record.py \
--data_dir=`pwd` \
--output_dir=`pwd`

在程序執行完後,你會發現兩個文件:train.record 和 val.record。

階段 2:訓練模型

步驟 1:模型選擇

如前所述,這是速度和準確率之間的權衡。同時,從頭開始創建並訓練一個目標檢測器是十分耗時的。因此,TensorFlow 目標檢測 API 提供了一堆預訓練模型,你可以在你的任務中對它們進行微調。這個過程被稱為遷移學習,可以大幅加快你的訓練過程。

教程|用深度學習DIY自動化監控系統

一堆在 MS COCO 數據集上的預訓練模型

下載其中一個模型,並將內容解壓到你的基礎目錄下。你將得到模型的 checkpoint、一個凍結推理圖 和一個 pipeline.config 文件。

步驟 2:定義訓練任務

你必須在 pipeline.config 文件中定義「訓練任務」。將文件放在基礎目錄下。真正重要的是文件的最後幾行—你只需要將突出高亮的值分別設置為自己的文件位置。

gradient_clipping_by_norm: 10.0
fine_tune_checkpoint: "model.ckpt"
from_detection_checkpoint: true
num_steps: 200000
}
train_input_reader {
label_map_path: "annotations/label_map.pbtxt"
tf_record_input_reader {
input_path: "train.record"
}
}
eval_config {
num_examples: 8000
max_evals: 10
use_moving_averages: false
}
eval_input_reader {
label_map_path: "annotations/label_map.pbtxt"
shuffle: false
num_epochs: 1
num_readers: 1
tf_record_input_reader {
input_path: "val.record"
}
}

步驟 3:開始訓練

執行以下命令以開始訓練。建議使用 GPU 足夠大的機器(假設你安裝了 TensorFlow 的 GPU 版本)以加速訓練過程。

python object_detection/train.py \
--logtostderr \
--pipeline_config_path=pipeline.config \
--train_dir=train

階段 3:推斷

步驟 1:導出訓練模型

在使用模型之前,你需要將訓練好的 checkpoint 文件導出到一個凍結的推理圖中。其實做比說起來容易——只需執行以下代碼(用 checkpoint 數字替換「xxxxx」):

python object_detection/export_inference_graph.py \
--input_type=image_tensor \
--pipeline_config_path=pipeline.config \
--trained_checkpoint_prefix=train/model.ckpt-xxxxx \
--output_directory=output

你將得到一個名為 frozen_inference_graph.pb 的文件,以及一堆 checkpoint 文件。

步驟 2:在視頻流上使用它

我們需要從視頻源中提取單幀。可以通過使用 OpenCV 的 VideoCapture 方法完成,如下所示:

cap = cv2.VideoCapture() 

flag = True
while(flag):
flag, frame = cap.read()
## -- Object Detection Code --

階段 1 中使用的數據提取代碼會自動創建一個包含測試集圖像的文件夾「test_images」。我們可以通過執行以下命令在測試集上運行我們的模型:

python object_detection/inference.py \
--input_dir={PATH} \
--output_dir={PATH} \
--label_map={PATH} \
--frozen_graph={PATH} \
--num_output_classes=1 \
--n_jobs=1 \
--delay=0

實驗

如前所述,在選擇目標檢測模型時,是在速度和準確度之間進行權衡。我進行了一些實驗,測量了使用三種不同模型檢測到的人的 FPS 和計數準確率。此外,實驗是在不同的資源約束(GPU 並行約束)上運行的。這些實驗的結果可以在選擇目標檢測模型時,為你提供一些有價值的見解。

設置

我們的實驗選擇了以下模型。這些可在 TensorFlow 目標檢測 API 的 Model Zoo 中找到。

  • 帶有 ResNet 50 的 Faster RCNN
  • 帶有 MobileNet v1 的 SSD
  • 帶有 InceptionNet v2 的 SSD

所有模型都在 Google Colab 上訓練 10 k 步(或直到它們的損失不再下降)。推理使用了 AWS p2.8xlarge 實例。通過比較模型檢測到的人數和真實結果來測量計數準確率。在以下約束條件下測試推理速度的每秒幀數(FPS):

  • 1 塊 GPU
  • 2 塊並行 GPU
  • 4 塊並行 GPU
  • 8 塊並行 GPU

結果

下圖是在我們的測試集上使用 FasterRCNN 生成的輸出的部分結果。更多結果將在下文的視頻中呈現。

教程|用深度學習DIY自動化監控系統

訓練時間

下圖展示了訓練每個模型 10 k 步(以小時為單位)所需的時間。這不包括超參數搜索所需的時間。

教程|用深度學習DIY自動化監控系統

當你的應用程序與用於遷移學習的預訓練模型大相徑庭時,你可能需要大幅調整超參數。但是,當你的應用程序與之類似時,你不需要進行大量搜索。儘管如此,你可能仍需要嘗試不同的訓練參數,例如學習率和優化器的選擇。

速度(每秒幀數)

這是我們實驗中最有趣的部分。如前所述,我們測量了三種模型在五種不同資源約束下的 FPS 性能。結果如下所示:

教程|用深度學習DIY自動化監控系統

當我們使用單塊 GPU 時,SSD 的速度極快,能輕鬆超越 Faster RCNN 的速度。但是,當我們增加(並行)GPU 的數量時,Faster RCNN 會迅速趕上 SSD 的速度。毋庸置疑,在一個低 GPU 環境下,採用帶有 MobileNet 的 SSD 比使用帶有 InceptionNet 的 SSD 要快得多。

上圖中的一個顯著特徵是,當我們為帶有 MobileNet 的 SSD 增加 GPU 數量時,FPS 略有下降。這個明顯的悖論實際上有一個簡單的解釋。事實證明,我們處理圖像的設置比圖像讀取函數提供的速度快!

視頻處理系統的速度不能快於圖像輸入系統的速度。

為了證明我的假設,我先啟動圖像讀取函數。下圖顯示了添加延遲時帶有 MobileNet 的 SSD 的 FPS 提升情況。早期圖表中,FPS 的輕微下降是由於多塊 GPU 請求輸入所涉及的開銷。

教程|用深度學習DIY自動化監控系統

毋庸置疑,我們發現如果引入延遲,FPS 會急劇增加。最重要的是,我們需要一個優化的圖像傳輸管道,以防止速度瓶頸的出現。但想將其應用在監控上還有一個瓶頸。監控攝像機的 FPS 設定了我們系統 FPS 的上限。

計算準確率

我們將計數準確率定義為我們的目標檢測系統正確識別的人的百分比。我覺得該定義用在監控方面更合適。以下是我們每個模型的表現:

教程|用深度學習DIY自動化監控系統

毋庸置疑,Faster RCNN 是最準確的模型。同樣令人驚訝的是,MobileNet 的性能優於 InceptionNet。

速度與準確率之間的權衡在實驗中顯而易見。但是,如果有足夠的資源,我們就可以以良好的 FPS 率使用高精度的模型。我們發現,使用 ResNet-50 的 Faster RCNN 準確率最高,並且當並行部署在 4+ 塊 GPU 上時,具有非常高的 FPS 率。

這有一大堆步驟!

這裡的步驟非常多。此外,為此模型設置一個實時工作的雲實例將是繁重且昂貴的。

一個更好的解決方案是使用已部署在服務器上的 API 服務,這樣你就只需考慮產品的開發了。這就是 Nanonets 的用武之地。他們將 API 部署在帶有 GPU 的高質量硬件上,這樣你就可以在沒有任何麻煩的情況下獲得意想不到的性能!

我將現有的 XML 註釋轉換為 JSON 格式並將其提供給 Nanonets API。事實上,如果你不想手動註釋數據集,可以請求它們為你添加註釋。以下是 Nanonets 負責繁重的工作時的簡化工作流程。

教程|用深度學習DIY自動化監控系統

使用 Nanonets 簡化工作流程

早些時候,我曾提到像微型無人機這樣的移動監控設備如何大大提高效率。我們可以使用類似 Raspberry Pi 的微控制器輕鬆地建造這樣的無人機,同時我們可以使用 API 調用來執行推斷。

開始使用 Nanonets API 進行目標檢測是非常簡單的,但若想要一篇講解清楚的指南,你可以查看這篇博文(https://medium.com/nanonets/how-to-easily-detect-objects-with-deep-learning-on-raspberrypi-225f29635c74)。

使用 Nanonets 的結果

Nanonets 花了大約 2 個小時才完成訓練。這包括超參數搜索所需的時間。就所費的訓練時間而言,Nanonets 是當仁不讓的贏家。Nanonets 在計數準確率方面也擊敗了 FasterRCNN。

FasterRCNN Count Accuracy = 88.77%
Nanonets Count Accuracy = 89.66%

以下是在我們的測試數據集上,所有 4 個模型的性能。很明顯,兩種 SSD 模型都有點不穩定並且準確率較低。此外,儘管 FasterRCNN 和 Nanonets 具有相當的精度,但後者具有更穩定的邊界框。

自動化監控可靠嗎?

深度學習是一種令人驚歎的工具,可以輕鬆提供典型的結果。但是,我們能在多大程度上信任我們的監控系統並放任其自動運行?在一些情況下,自動化是令人懷疑的。

更新:鑑於 GDPR 和下述原因,我們有必要思考監控自動化的合法性和道德問題。此博文僅用於教育目的,文中使用了一個公開的數據集。你有責任確保你的自動化系統符合你所在地區的法律。

1. 不太可靠的結論

我們不知道深度學習算法如何得出結論。即使數據輸入過程無可挑剔,也可能存在大量的虛假數據。例如,英國警察使用的 AI 鑑黃過濾器不斷將沙丘圖像誤判為裸體圖像而將其刪除。有引導的反向傳播等技術可以在一定程度上解釋決策,但我們還有很長的路要走。

2. 對抗性攻擊

深度學習系統非常脆弱。對抗性攻擊類似於圖像分類器的光學錯覺。但可怕的是,一個計算出的不明顯的擾動會迫使深度學習模型進行錯誤分類。依據相同的原理,研究人員能夠通過使用「對抗眼鏡」(adversarial glasses)來避免基於深度學習的監控系統出現錯誤。

3. 假正類

另一個問題是,如果出現假正類,我們該怎麼做。問題的嚴重程度取決於應用程序本身。例如,邊境巡邏系統的假正類可能比花園監控系統更重要。應該有一些人為干預以避免意外。

4. 相似的面孔

可悲的是,你的外觀並不像你的指紋那麼獨一無二。兩個人(或更多人)看起來非常相似是可能的。同卵雙胞胎是最好的例子之一。據報道,蘋果的 Face ID 無法區分兩個無親屬關係的中國員工。這會使監控和識別人變得更難。

5. 數據集缺乏多樣性

你提供多好的數據,深度學習算法就有多好。最受歡迎的人臉數據集只有白人樣本。對於孩子來說,人類存在各種膚色似乎是顯而易見的,但深度學習算法卻有點傻。谷歌就曾因為將一個黑人錯誤地歸類為大猩猩而陷入麻煩。


分享到:


相關文章: