當前位置:
首頁 > 最新 > 如何使用Docker、TensorFlow目標檢測API和OpenCV實現實時目標檢測和視頻處理

如何使用Docker、TensorFlow目標檢測API和OpenCV實現實時目標檢測和視頻處理

選自TowardsDataScience

作者:Léo Beaucourt

機器之心編譯

參與:李詩萌、路雪

本文展示了如何使用 Docker 容器中的 TensorFlow 目標檢測 API,通過網路攝像頭執行實時目標檢測,同時進行視頻後處理。作者使用的是 OpenCV 和 Python3 多進程和多線程庫。本文重點介紹了項目中出現的問題以及作者採用的解決方案。

完整代碼地址:https://github.com/lbeaucourt/Object-detection

GIF

用 YouTube 視頻進行視頻處理測試

動機

我是從這篇文章《Building a Real-Time Object Recognition App with Tensorflow and OpenCV》(https://towardsdatascience.com/building-a-real-time-object-recognition-app-with-tensorflow-and-opencv-b7a2b4ebdc32)開始探索實時目標檢測問題,這促使我研究 Python 多進程庫,使用這篇文章(https://www.pyimagesearch.com/2015/12/21/increasing-webcam-fps-with-python-and-opencv/)中介紹的方法提高每秒幀數(frames per second,FPS)。為了進一步加強項目的可移植性,我試著將自己的項目整合到 Docker 容器中。這一過程的主要困難在於處理流入和流出容器的視頻流。

此外,我還在項目中添加了視頻後處理功能,這一功能也使用了多進程,以減少視頻處理的時間(如果使用原始的 TensorFlow 目標檢測 API 處理視頻,會需要非常非常長的時間)。

在我的個人電腦上可以同時進行高性能的實時目標檢測和視頻後處理工作,該過程僅使用了 8GB 的 CPU。

用於數據科學的 Docker

鑒於大量文章對 TensorFlow 目標檢測 API 的實現進行了說明,因此此處不再贅述。作為一名數據科學家,我將展示如何在日常工作中使用 Docker。請注意,我用的是來自 Tensorflow 的經典 ssd_mobilenet_v2_coco 模型。我在本地複製了模型(.pb 文件)和對應的標籤映射,以便後續個人模型的運行。

我相信現在使用 Docker 已經是數據科學家最基礎的技能了。在數據科學和機器學習的世界中,每周都會發布許多新的演算法、工具和程序,在個人電腦上安裝並測試它們很容易讓系統崩潰(親身經歷!)。為了防止這一悲慘事件的發生,我現在用 Docker 創建數據科學工作空間。

你可以在我的庫中找到該項目的相關 Docker 文件。以下是我安裝 TensorFlow 目標檢測的方法(按照官方安裝指南進行):

同樣,我還安裝了 OpenCV:

建立圖像會花幾分鐘的時間,但是之後用起來就會又快又容易。

實時目標檢測

首先我試著將目標檢測應用於網路攝像頭視頻流。《Building a Real-Time Object Recognition App with Tensorflow and OpenCV》完整地介紹了這項工作的主體部分。困難在於如何將網路攝像頭視頻流傳送到 Docker 容器 中,並使用 X11 伺服器恢復輸出流,使視頻得以顯示出來。

將視頻流傳送到容器中

使用 Linux 的話,設備在 /dev/ 目錄中,而且通常可以作為文件進行操作。一般而言,你的筆記本電腦攝像頭是「0」設備。為了將視頻流傳送到 docker 容器中,要在運行 docker 圖像時使用設備參數:

對 Mac 和 Windows 用戶而言,將網路攝像頭視頻流傳送到容器中的方法就沒有 Linux 那麼簡單了(儘管 Mac 是基於 Unix 的)。本文並未對此進行詳細敘述,但 Windows 用戶可以使用 Virtual Box 啟動 docker 容器來解決該問題。

從容器中恢復視頻流

解決這個問題時花了我一些時間(但解決方案仍舊不盡如人意)。我在 http://wiki.ros.org/docker/Tutorials/GUI 網頁發現了一些使用 Docker 圖形用戶界面的有用信息,尤其是將容器和主機的 X 伺服器連接,以顯示視頻。

首先,你必須要放開 xhost 許可權,這樣 docker 容器才能通過讀寫進 X11 unix socket 進行正確顯示。首先要讓 docker 獲取 X 伺服器主機的許可權(這並非最安全的方式):

在成功使用該項目後,再將控制許可權改回默認值:

創建兩個環境變數 XSOCK 和 XAUTH:

XSOCK 指 X11 Unix socket,XAUTH 指具備適當許可權的 X 認證文件:

最後,我們還要更新 docker 運行的命令行。我們發送 DISPLAY 環境變數,為 X11 Unix socket 和帶有環境變數 XAUTHORITY 的 X 認證文件安裝卷:

現在我們可以運行 docker 容器了,而它完成後是這樣的:

工作中的我和其他物體(因為害羞就不露臉了)。

儘管主機配置有 X 伺服器,但我還是無法完全刪除我代碼中疑似錯誤的部分。OpenCV 需要通過調用 Python 腳本使用 cv2.imshow 函數進行「初始化」。我收到了以下錯誤信息:

然後,我可以調用 Python 主腳本(my-object-detection.py),視頻流也可以發送到主機的顯示器了。我對使用第一個 Python 腳本初始化 X11 系統的解決方法並不十分滿意,但是我尚未發現其他可以解決這一問題的辦法。

視頻處理

為了成功用網路攝像頭實時運行目標檢測 API,我用了線程和多進程 Python 庫。線程用來讀取網路攝像頭的視頻流,幀按隊列排列,等待一批 worker 進行處理(在這個過程中 TensorFlow 目標檢測仍在運行)。

就視頻處理而言,使用線程是不可能的,因為必須先讀取所有視頻幀,worker 才能對輸入隊列中的第一幀視頻應用目標檢測。當輸入隊列滿了時,後面讀取的視頻幀會丟失。也許使用大量 worker 和多個隊列可以解決這一問題(但會產生大量的計算損失)。

簡單隊列的另一個問題是,由於分析時間不斷變化,輸出隊列中的視頻幀無法以與輸入隊列相同的順序發布。

為了添加視頻處理功能,我刪除了讀取視頻幀的線程,而是通過以下代碼來讀取視頻幀:

如果輸入隊列未滿,則接下來會從視頻流中讀取下一個視頻幀,並將其放到隊列中去。否則輸入隊列中沒有視頻幀是不會進行任何處理的。

為了解決視頻幀順序的問題,我使用優先順序隊列作為第二輸出隊列:

1. 讀取視頻幀,並將視頻幀及其對應的編號一併放到輸入隊列中(實際上是將 Python 列表對象放到隊列中)。

2.然後,worker 從輸入隊列中取出視頻幀,對其進行處理後再將其放入第一個輸出隊列(仍帶有相關的視頻幀編號)。

3. 如果輸出隊列不為空,則提取視頻幀,並將視頻幀及其對應編號一起放入優先順序隊列,視頻編號即為優先順序編號。優先順序隊列的規模被設置為其他隊列的三倍。

4. 最後,如果輸出優先順序隊列不為空,則取出優先順序最高(優先順序編號最小)的視頻(這是標準優先順序隊列的運作)。如果優先順序編號與預期視頻幀編號一致,則將這一幀添加到輸出視頻流中(如果有需要的話將這一幀寫入視頻流),不一致的話則將這一幀放回優先順序隊列中。

要停止該進程,需要檢查所有的隊列是否為空,以及是否從該視頻流中提取出所有的視頻了。

總結

本文介紹了如何使用 docker 和 TensorFlow 實現實時目標檢測項項目。如上文所述,docker 是測試新數據科學工具最安全的方式,也是我們提供給客戶打包解決方案最安全的方式。本文還展示了如何使用《Building a Real-Time Object Recognition App with Tensorflow and OpenCV》中的原始 Python 腳本執行多進程視頻處理。

本文為機器之心編譯,轉載請聯繫本公眾號獲得授權。

------------------------------------------------


喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 機器之心 的精彩文章:

奇異值分解簡介:從原理到基礎機器學習應用
PyTorch為何如此高效好用?來探尋深度學習框架的內部架構

TAG:機器之心 |