科技

走親訪友不慌!手把手教你怎樣用Mask R-CNN和Python做一個搶車位神器

大資料文摘出品

編譯:李雷、笪潔瓊、Aileen、ZoeY

今天是大年初三,按照傳統習俗,從這天開始,就要開始走親訪友了。這時候的商場、飯館也都是“人聲鼎沸”,畢竟走親戚串門必不可少要帶點禮品、聚餐喝茶。

熱鬧歸熱鬧,這個時候最難的問題可能就是怎樣從小區、商場、菜市場的人山人海里準確定位,找到一個“車位”。

別慌!

一位名叫Adam Geitgey的軟體工程師、AI軟體工程博主也被“停車難”的問題困擾已久。為了讓自己能給迅速定位空車位,他用例項分割模型Mask R-CNN和python寫了一個搶佔停車位的小程式。

以下是作者以第一人稱給出的教程,enjoy。

我住在一個大都市,但就像大多數城市一樣,在這裡很難找到停車位。停車場總是停得滿滿的,即使你自己有私人車位,朋友來訪的時候也很麻煩,因為他們找不到停車位。

我的解決方法是:

用攝像頭對著窗外拍攝,並利用深度學習演算法讓我的電腦在發現新的停車位時給我發簡訊。

這可能聽起來相當複雜,但是用深度學習來構建這個應用,實際上非常快速和簡單。有各種現有的實用工具 - 我們只需找到這些工具並且將它們組合在一起。

現在,讓我們花幾分鐘時間用Python和深度學習建立一個高精度的停車位通知系統吧!

分解問題

當我們想要通過機器學習解決一個複雜的問題時,第一步是將問題分解為簡單任務的列表。然後,對於每個簡單任務,我們可以從機器學習工具箱中找尋不同的工具來解決。

通過將這些簡單問題的解決方案串起來形成框架(例如下面的思維導圖),我們將實現一個可以執行復雜操作的系統。

以下就是我如何將檢測公共停車位的問題分解並形成流程:

機器學習模型流程的輸入是來自對著窗外的普通網路攝像頭的視訊:

我的攝像頭拍下的視訊類似上圖

我們將每一幀視訊送入模型裡,一次一幀。

流程的第一步是檢測視訊幀中所有可能的停車位。顯然,我們需要知道影象的哪些部分是停車位才能檢測到哪些停車位是空的。

第二步是識別每幀視訊中所有的汽車,這樣我們可以跟蹤每輛車在幀與幀之間的位移。

第三步是確定哪些停車位上目前有汽車,哪些沒有。這需要綜合第一步和第二步的結果。

最後一步是在停車位空出來的時候傳送通知。這是基於視訊幀之間的汽車位置的變化。

我們可以使用各種技術以多種不同方式完成這些步驟。構建流程的方法不是唯一的,不同的方法沒有對錯,但有不同的優點和缺點。現在讓我們來看看每一步吧!

檢測影象中的停車位

以下是相機拍到的影象:

我們需要能夠掃描該影象並返回可以停車的區域列表,如下所示:

街區上可用的停車位

有一種偷懶的方法是手動將每個停車位的位置編入到程式中,而不是自動檢測停車位。但是如果我們移動相機或想要檢測不同街道上的停車位時,我們必須再次手動輸入停車位的位置。這太不爽了,所以讓我們找到一種自動檢測停車位的方法。

一個想法是尋找停車計費表並假設每個計費表旁邊都有一個停車位:

在圖片中檢測的停車計費表

但這種方法存在一定的問題。首先,並非每個停車位都有停車咪表 – 實際上,我們最感興趣的是找到免費停車位!其次,停車咪表的位置並不能確切地告訴我們停車位的具體位置,只能讓我們離車位更接近一點。

另一個想法是建立一個物體檢測模型,尋找在道路上繪製的停車位斜線標記,如下所示:

留意那些微小的黃色標記,這些是在道路上繪製每個停車位的邊界。

但這種做法也很痛苦。首先,我所在城市的停車位斜線標記非常小,從遠處很難看清,電腦也難以察覺。第二,街道上到處都是各種不相關的線條和標記,所以要區分哪些線條是停車位,哪些線條是車道分隔線或人行橫道是很困難的。

每當遇到一個看似困難的問題時,請先花幾分鐘時間看看是否能夠採用不同的方式來避免某些技術難點並解決問題。到底什麼是停車位呢?停車位就是車輛停留很長一段時間的地方。因此也許我們根本不需要檢測停車位。為什麼我們不能只檢測那些長時間不動的車並假設它們停在停車位上?

換句話說,真正的停車位只是容納了非移動中的車輛的區域:

這裡每輛車的邊框實際上都是一個停車位!如果我們能夠檢測到靜止的汽車,就不需要真的去檢測停車位。

因此,如果我們能夠檢測到汽車並找出哪些汽車在視訊的每幀之間沒有移動,我們就可以推斷停車位的位置。這就變得很容易了!

檢測影象中的汽車

檢測視訊每幀中的汽車是一個標準的物件檢測問題。我們可以使用許多種機器學習方法來檢測影象中的物件。以下是一些從過去到現在最常見的物件檢測演算法:

訓練一個HOG(梯度方向直方圖)物體探測器滑過(掃描)我們的影象以找到所有的汽車。這種比較古老的非深度學習方法執行起來相對較快,但它對於朝向不同方向的汽車不能很好地處理。

訓練CNN(卷積神經網路)物體探測器閱覽(掃描)我們的影象,直到我們找到所有的汽車。這種方法雖然準確,但效率不高,因為我們必須使用CNN演算法多次掃描同一影象才能找到其中的所有汽車。雖然它可以很容易地找到朝向不同方向的汽車,但它需要比基於HOG的物體探測器更多的訓練資料。

使用更新的深度學習方法,如Mask R-CNN,快速R-CNN或YOLO,將CNN的準確性與巧妙設計和效率技巧相結合,可以大大加快檢測過程。即使有大量訓練資料來訓練模型,這種方法的速度也相對較快(在GPU上)。

一般來說,我們希望選擇最簡單的解決方案,以最少的訓練資料完成工作,而不是最新、最花哨的演算法。但在這種特殊情況下,Mask R-CNN對我們來說是一個比較合理的選擇,儘管它相當花哨新潮。

Mask R-CNN架構的設計理念是在不使用滑動視窗方法的情況下以高計算效率的方式檢測整幅影象上的物件。換句話說,它執行得相當快。使用最新GPU,我們可以以每秒幾幀的速度檢測高解析度視訊中的物件。那對於這個專案來說應該沒問題。

此外,Mask R-CNN對每個檢測到的物件給出了大量資訊。大多數物件檢測演算法僅返回每個物件的邊界。但Mask R-CNN不僅會給我們每個物件的位置,還會給我們一個物件輪廓(或概述),如下所示:

為了訓練Mask R-CNN,我們需要大量的包含我們想要檢測的物件的圖片。我們可以去拍攝汽車照片並檢測這些照片中的所有汽車,但這需要幾天的工作。幸運的是,汽車是許多人想要檢測的常見物體,因此已經有不少汽車影象的公共資料集。

其中一個名為COCO (Common Objects in Context)的流行資料集,其中包含標註了物件輪廓的影象。在此資料集中,有超過12,000張做了標註的汽車影象。以下是COCO資料集中的其中一張:

COCO資料集中的影象,其中已經標出了物件。

這個資料集非常適合訓練Mask R-CNN模型。

等等,還有更好的事!由於太多人使用COCO資料集構建物件檢測模型,很多人已經完成並共享了他們的結果。因此,我們可以從預先訓練好的模型開始,而無需訓練我們自己的模型,這種模型可以即插即用。對於這個專案,我們將使用來自Matterport的大型開源Mask R-CNN實現專案,它自帶預先訓練的模型。

旁註:不要害怕訓練一個定製的Mask R-CNN目標探測器!註釋資料是很費時,但並不難。

如果我們在攝像頭拍攝的影象上執行預先培訓過的模型,就會得到如下的結果:

在我們的影象上,識別出了COCO資料集中的預設物件-汽車、人、交通燈和一棵樹。

我們不僅能識別汽車,還能識別交通燈和人。幽默的是,其中一棵樹被識別成一個“盆栽植物”。

對於影象中檢測到的每一個物體,我們從Mask R-CNN模型中都會得到以下四個資料:

1.檢測到的物件型別(以整數形式表示)。經過預先訓練的COCO模型知道如何檢測80種不同的常見物體,如汽車和卡車。這是80種的常見物體的完整清單https://gist.github.com/ageitgey/b143ee809bf08e4927dd59bace44db0d。

2.目標檢測的置信度得分。數值越高,模型就越確定它正確地識別了物件。

3.影象中物件的邊界框,以X/Y畫素位置表示。

4.點陣圖圖層告訴我們邊界框中的哪些畫素是物件的一部分,哪些不是。通過圖層資料,我們還可以計算出物件的輪廓。

下面是使用Matterport’s Mask R-CNN中的預培訓模型和OpenCV共同實現汽車邊界框檢測的Python程式碼:

當您執行該程式碼時,會看到影象上每輛被檢測到的汽車周圍都有一個邊框,如下所示:

被檢測到的每輛汽車周圍都有一個綠色的邊框。

您還可以在控制檯中檢視每個被檢測到的汽車的畫素座標,如下所示:

Cars found in frame of video:

Car:

Car:

Car:

有了這些資料,我們已經成功地在影象中檢測到了汽車。可以進行下一步了!

檢測空車位

我們知道影象中每輛車的畫素位置。通過連續檢視多幀視訊,我們可以很容易地確定哪些車輛沒有移動,並假設這些區域是停車位。但我們如何檢測汽車何時離開停車位呢?

主要問題是,我們的影象中汽車的邊界框有部分重疊:

即使對於不同停車位的汽車,每輛車的邊界框也有一點重疊。

因此,如果我們假設每一個邊界框中的都代表一個停車位,那麼即使停車位是空的,這個邊界框也可能有一部分被汽車佔據。我們需要一種方法來測量兩個物件重疊的程度,以便檢查“大部分是空的”的邊框。

我們將使用交併比(Intersection Over Union ,IoU)方法。用兩個物件重疊的畫素數量除以兩個物件覆蓋的畫素總數量,如下所示:

IoU可以告訴我們汽車邊界框與停車位邊界框的重疊程度。有了這個指標,我們就可以很容易地確定一輛車是否在停車位。如果IoU測量值很低,比如0.15,這意味著這輛車並沒有佔用太多的停車位。但是如果測量值很高,比如0.6,這意味著汽車佔據了大部分的停車位,那麼我們可以確定停車位被佔用了。

由於IoU在計算機視覺中是一種常見的度量方法,所以通常您使用的庫已經有相關實踐。事實上,Matterport Mask R-CNN庫中就有這樣的函式mrcnn.utils.compute_overlaps,我們可以直接呼叫這個函式。

假設在影象中有一個表示停車區域的邊界框列表,那麼檢查被檢測到的車輛是否在這些邊界框中,就如同新增一行或兩行程式碼一樣簡單。

結果如下:

[

[1. 0.070400320. 0.]

[0.070400321. 0.076731650.]

[0. 0. 0.023321120.]

]

在這個二維陣列中,每一行表示一個停車位的邊界框。相應的,每列表示該停車位與被檢測到的汽車有多少重疊。1.0分意味著汽車完全佔據了停車位,而0.02分這樣的低分意味著汽車只是接觸了停車位邊界框,但並沒有佔據很多區域。

為了找到空置的停車位,我們只需要檢查這個陣列中的每一行。如果所有的數字都是零或者非常小的數字,就意味著沒有東西佔據了這個空間,因此它就是空閒的!

但請記住,物體檢測並不總是與實時視訊完美結合。儘管Mask R-CNN非常準確,但偶爾它會在一幀視訊中錯過一兩輛車。因此,在將停車位標記為空閒之前,我們應該確保它在一段時間內都是空閒的,可能是5或10幀連續視訊。這將防止僅僅在一幀視訊上出現暫時性的物體檢測問題而誤導系統將停車位判定為空閒。但當我們看到至少有一個停車位在連續幾幀視訊影象中都被判定為空閒,我們就可以傳送簡訊了!

傳送簡訊

最後一步是當我們注意到一個停車位在連續幾幀視訊影象中都被判定為空閒時,就傳送一條簡訊提醒。

使用 Twilio從Python傳送短訊息非常簡單。Twilio是一個流行的介面,它可以讓您用幾行程式碼從任何程式語言傳送短訊息。當然,如果您喜歡使用其他的簡訊服務提供者,也是可以的。我和Twilio沒有利害關係。只是第一個就想到了它。

Twilio:

要使用Twilio,需要註冊試用帳戶,建立Twilio電話號碼並獲取您的帳戶憑據。然後,您需要安裝Twilio Python客戶端的庫:

pip3 install twilio

安裝後,使用下面的程式碼(需要將關鍵資訊替換成您的賬戶資訊),就可以從Python傳送簡訊了:

from twilio.rest import Client

# Twilio account details

twilio_account_sid = 'Your Twilio SID here'

twilio_auth_token = 'Your Twilio Auth Token here'

twilio_source_phone_number = 'Your Twilio phone number here'

# Create a Twilio client object instance

client = Client(twilio_account_sid, twilio_auth_token)

# Send an SMS

message = client.messages.create(

body="This is my SMS message!",

from_=twilio_source_phone_number,

to="Destination phone number here"

)

直接將程式碼插入到我們的腳本里,就可以添加發送簡訊的功能了。但我們需要注意的是,如果一個停車位一直是空閒的,就不需要在每一幀視訊都給自己傳送簡訊了。因此,我們需要有一個標誌來標記我們是否已經發送了一條簡訊,並確保在經過一定時間或檢測到其他停車位空閒之前,我們不會再發送另一條簡訊息。

打包組裝

我們將流程中的每個步驟寫成了一個單獨的Python指令碼。以下是完整的程式碼:

此部分程式碼太長,感興趣的同學可以在下面的網址中找到:

https://medium.com/@ageitgey/snagging-parking-spaces-with-mask-r-cnn-and-python-955f2231c400

要執行此程式碼,您需要首先安裝Python 3.6+, Matterport Mask R-CNN和OpenCV。

Matterport Mask R-CNN:

OpenCV:

我有意讓程式碼儘可能簡明扼要。例如,它只是假設在第一幀視訊中出現的任何汽車都是已停放的汽車。試試修改程式碼,看看您能不能提高它的可靠性。

不用擔心修改此程式碼就不能適應不同的場景。只需更改模型搜尋的物件ID,就可以將程式碼完全轉換為其他內容。例如,假設您在滑雪場工作。通過一些調整,您可以將此指令碼轉換為一個自動檢測滑雪板從斜坡上跳下的系統,並記錄炫酷的滑雪板跳躍軌跡。或者,如果您在一個遊戲保護區工作,您可以把這個指令碼變成一個用來計數在野外能看到多少斑馬的系統。

唯一的限制就是你的想象力。

一起來試試吧!

相關報道:

志願者介紹

後臺回覆“志願者”加入我們

聽說點了「好看」的人都變好看了哦

Reference:科技日報

看更多!請加入我們的粉絲團

轉載請附文章網址

不可錯過的話題