情境:
有一垂直地面向下拍攝的鏡頭,地面上放有一固定位置的圓形(從鏡頭的角度看)物體作為辨識的目標(biāo),鏡頭可能會在固定的高度水平移動,也就是目標(biāo)大小基本不變,要考慮目標(biāo)可能在畫面中位置的變化。假設(shè)目標(biāo)不總是出現(xiàn)在畫面中,鏡頭移動時目標(biāo)可能會跑到畫面外,目標(biāo)有大約90%以上的面積出現(xiàn)在畫面中時,需要能夠?qū)⑵浔孀R出來。
寫一支程式在以上敘述的情景中辨識出目標(biāo),假設(shè)地面除了目標(biāo)外,沒有其他圓形物體,但是要考慮到地面雜訊的干擾。
以上是最近處理到的一個情況,實際做起來不難,順便就在這邊分享一些內(nèi)容。這邊以Python的一些語法或結(jié)構(gòu)做討論,如果需要C++的協(xié)助,也歡迎提出。
請注意這邊僅分享部分程式內(nèi)容及概念,不會放上完整程式碼。
首先這個問題最主要就是要找到畫面中的圓,我們可以直接用OpenCV 的HoughCircles 來實現(xiàn),以下是使用OpenCV 官方文件中的參數(shù)找到畫面中的圓的結(jié)果:
想當(dāng)然結(jié)果慘不忍睹,因為參數(shù)沒有根據(jù)情況調(diào)整。
接著調(diào)了一下參數(shù)後:
這邊第一個問題就出現(xiàn)了,因為演算法的關(guān)係,一些肉眼看起來不是圓的地方也剛好被當(dāng)成圓了,考慮到現(xiàn)實情況,如果直接用演算法處理這些圓的話會沒完沒了。如果再把參數(shù)調(diào)得更嚴(yán)格,則變成有時候目標(biāo)的圓也會偵測不到。
我們再回去分析這個情境:
? 場景中只有一個圓形物體是我們的目標(biāo)
? 場景中除了目標(biāo)外沒有其他圓形物體
? 影像是連續(xù)拍攝的
這邊先看第一點,既然只有一個目標(biāo),那麼我們可以直接透過操作參數(shù),來找到畫面中最有可能是圓的物體。
要做到這點,可以直接將HoughCircles 中的minDist,也就是兩個圓心之間的最短距離,設(shè)為“畫面對角距離+2×最大半徑+1”,這樣一來就可以保證畫面中只找到一個圓,而假設(shè)我們的目標(biāo)在畫面中,場景中又沒有其他圓,這邊找到的圓就可以確定有很高的機(jī)率是我們要的了。(其他參數(shù)應(yīng)照實際狀況調(diào)整)
只是要注意,這樣做HoughCircles運算時間可能會大幅上升 (這邊不考慮這個問題)。
我們現(xiàn)在已經(jīng)可以在目標(biāo)出現(xiàn)時,找到我們要的目標(biāo),現(xiàn)在考慮到目標(biāo)不在畫面中的情況 (另一段影像的截圖):
可以看到假如畫面中沒有目標(biāo),仍可能會誤判 (雖然用來測試的3段影片只出現(xiàn)這一幀誤判)。
如果參數(shù)調(diào)整得好,這個情形可以改善很多,但有沒有更好的辦法確保不會出現(xiàn)誤判呢?
這時候就真的要寫一點演算法來處理了,基本的概念是:
假如目標(biāo)有出現(xiàn)在畫面中,連續(xù)的影像應(yīng)該要能夠在接近的位置拍攝到半徑接近的圓形;假如目標(biāo)不在畫面中,即使有在畫面中找到圓形,這個圓形在接下來幾幀的位置和半徑都會劇烈變化,因為這只是畫面中幾個點湊巧連成的圓。
這邊我們就可以透過處理連續(xù)幾幀的圓形偵測結(jié)果,判斷畫面中找到的圓是目標(biāo),或者只是雜訊。
首先看圓形偵測的部分,我們有一個長度為5的陣列,每個位置的初始值為None,每次都將在新一幀畫面找到的圓的資訊存入陣列尾端,如果找不到圓則存入None,接著將陣列最前端的元素移除,讓陣列始終保持在長度為5。如此一來我們就有了連續(xù)5幀圓形偵測的結(jié)果。
假設(shè)我們?nèi)?張連續(xù)的影像,設(shè)定一個信心值60%,那麼在這5張影像中,要有3張是包含位置和半徑接近的圓,這幾個圓的最後一個圓才會被當(dāng)成現(xiàn)在的目標(biāo)。
執(zhí)行結(jié)果:
當(dāng)然這個演算法還可以更快,只是這邊我們只取5張影像找到的圓做運算,實際上光是HoughCircles 返回結(jié)果的時間就會是這個演算法需要的幾十甚至幾千倍(取決於影像大小),再加上這個方式個人覺得容易理解與維護(hù),所以就不再修改。
如果需要再進(jìn)一步講解程式內(nèi)容,或是覺得哪邊有問題,都?xì)g迎詢問。
雖然說不會透漏完整程式碼,但好像重點都貼上來了w