視頻遮擋檢測(cè)與運(yùn)動(dòng)檢測(cè)實(shí)現(xiàn):從取幀鏈路到參數(shù)調(diào)優(yōu))
攝像頭被一塊布蒙住、鏡頭被噴漆、安裝角度被外力掰偏監(jiān)控畫面看起來(lái)“沒(méi)變化”但后臺(tái)值班人員可能幾天都沒(méi)發(fā)現(xiàn)反過(guò)來(lái)畫面里有人走動(dòng)要不要觸發(fā)告警、要不要聯(lián)動(dòng)抓拍這是每一臺(tái)智能IPC都繞不開(kāi)的兩個(gè)基礎(chǔ)功能。視頻遮擋檢測(cè)和運(yùn)動(dòng)檢測(cè)在MPP多媒體處理平臺(tái)開(kāi)發(fā)里屬于看起來(lái)簡(jiǎn)單、做起來(lái)全是細(xì)節(jié)的模塊。算法層面不復(fù)雜難點(diǎn)在于數(shù)據(jù)鏈路怎么選、參數(shù)怎么配、誤報(bào)漏報(bào)怎么壓。這篇文章想梳理我在MPP平臺(tái)上實(shí)現(xiàn)這兩類功能時(shí)的完整思路包括取幀鏈路、核心算法邏輯、參數(shù)含義、防誤報(bào)設(shè)計(jì)以及現(xiàn)場(chǎng)調(diào)試時(shí)頻繁踩到的坑。適合正在做智能IPC、攝像頭定制開(kāi)發(fā)的工程師或者剛接觸平臺(tái)SDK、想快速上手遮擋和移動(dòng)偵測(cè)的同學(xué)。內(nèi)容不涉及具體芯片型號(hào)只講平臺(tái)通用的實(shí)現(xiàn)套路你拿到任何帶MPP接口的開(kāi)發(fā)板都能對(duì)照著落。1. 視頻遮擋與運(yùn)動(dòng)檢測(cè)的實(shí)際場(chǎng)景與模塊選型1.1 遮擋檢測(cè)到底解決什么問(wèn)題遮擋檢測(cè)的核心不是“認(rèn)出畫面里是什么”而是判斷“畫面本身是否還正?!?。它服務(wù)的場(chǎng)景非常明確攝像機(jī)被惡意遮擋比如用布、紙板、噴漆堵住鏡頭畫面變成一片黑、一片白或一片均勻色。鏡頭因震動(dòng)或人為破壞發(fā)生視角偏移畫面內(nèi)容對(duì)著天空、墻面或地面雖然顏色正常但已經(jīng)失去監(jiān)控價(jià)值。鏡頭臟污、起霧、進(jìn)灰畫面長(zhǎng)期模糊。這類問(wèn)題的共同點(diǎn)是畫面統(tǒng)計(jì)特征發(fā)生異常。正常監(jiān)控畫面通常有較豐富的邊緣、紋理亮度分布有層次遮擋后畫面會(huì)趨于均勻亮度極端化邊緣密度急劇下降。所以遮擋檢測(cè)不需要神經(jīng)網(wǎng)絡(luò)不需要目標(biāo)識(shí)別只需要對(duì)每幀圖像算幾個(gè)統(tǒng)計(jì)量再用閾值判斷即可。這個(gè)功能的價(jià)值在于“監(jiān)控的可靠性”。一臺(tái)攝像機(jī)如果畫面早就失效了后面接再?gòu)?qiáng)的AI分析都是白搭。很多項(xiàng)目把遮擋檢測(cè)和“設(shè)備在線狀態(tài)”放在一起看一旦觸發(fā)就派單巡檢或者彈窗告警。1.2 運(yùn)動(dòng)檢測(cè)在智能設(shè)備上的定位運(yùn)動(dòng)檢測(cè)解決的又是另一類需求感知場(chǎng)景中的物體移動(dòng)并基于移動(dòng)狀態(tài)產(chǎn)生聯(lián)動(dòng)行為。典型場(chǎng)景包括無(wú)人值守區(qū)域有人闖入產(chǎn)生告警并聯(lián)動(dòng)抓拍、錄像。私有區(qū)域在布防時(shí)段出現(xiàn)物體移動(dòng)通知用戶??土鹘y(tǒng)計(jì)、人流方向判斷等前置步驟。運(yùn)動(dòng)檢測(cè)通常不關(guān)心移動(dòng)的是什么物體只關(guān)心“有沒(méi)有像素塊發(fā)生變化”。它比AI人形檢測(cè)粗糙但勝在計(jì)算量極低、全天候穩(wěn)定運(yùn)行適合作為第一層篩選。很多設(shè)備是先跑運(yùn)動(dòng)檢測(cè)一旦觸發(fā)再調(diào)用更重的檢測(cè)模型去判斷是不是人、是不是車這樣能把算力用在刀刃上。在MPP平臺(tái)里遮擋檢測(cè)和運(yùn)動(dòng)檢測(cè)經(jīng)常是“共路復(fù)用的”。它們都只需要低分辨率的灰度或YUV數(shù)據(jù)都只需要跑統(tǒng)計(jì)或差分邏輯所以可以共用同一路縮放后的視頻幀分時(shí)或分線程執(zhí)行。1.3 先用硬件能力還是自己算這是平臺(tái)開(kāi)發(fā)里第一個(gè)要拍板的取舍。不同芯片方案的SDK能力差別很大有些平臺(tái)提供硬件運(yùn)動(dòng)檢測(cè)模塊直接在編碼鏈路里輸出運(yùn)動(dòng)區(qū)域位圖有些平臺(tái)只有VGS視頻圖形子系統(tǒng)縮放能力運(yùn)動(dòng)檢測(cè)得自己去用戶態(tài)算。我沒(méi)有辦法給你一個(gè)統(tǒng)一答案只講我自己的判斷標(biāo)準(zhǔn)如果SDK明確提供了硬件MD運(yùn)動(dòng)檢測(cè)和遮擋檢測(cè)通道優(yōu)先用硬件通道。硬件通道不占用CPU檢測(cè)效果好缺點(diǎn)是參數(shù)調(diào)節(jié)范圍相對(duì)固定底層細(xì)節(jié)看不到。如果SDK沒(méi)有硬件檢測(cè)或者硬件檢測(cè)的ROI、靈敏度不能滿足項(xiàng)目需求就用VGS把YUV縮放到小分辨率再在用戶態(tài)用幀差法做運(yùn)動(dòng)檢測(cè)、用統(tǒng)計(jì)特征做遮擋檢測(cè)。我自己更傾向于“用戶態(tài)檢測(cè)硬件輔助”的組合。原因是現(xiàn)場(chǎng)調(diào)試時(shí)用戶態(tài)代碼可以把統(tǒng)計(jì)值、中間結(jié)果全部打出來(lái)定位問(wèn)題非常直觀。硬件模塊往往只能看成敗標(biāo)志一旦誤報(bào)很難判斷是閾值問(wèn)題還是驅(qū)動(dòng)問(wèn)題。2. 檢測(cè)數(shù)據(jù)鏈路設(shè)計(jì)分辨率、幀率與ROI2.1 從哪條鏈路取檢測(cè)幀很多第一次做MPP開(kāi)發(fā)的工程師會(huì)直接去取編碼前的原始YUV甚至去讀RAW圖來(lái)做運(yùn)動(dòng)檢測(cè)。這么做最大的問(wèn)題有兩個(gè)一是原始分辨率太大用戶態(tài)計(jì)算吃CPU二是取流路徑可能和編碼器搶帶寬影響主碼流幀率。我常用的做法是在編碼前設(shè)置一個(gè)VGS通道把輸入幀縮放成一路專門給檢測(cè)功能的“小圖”。具體流程如下VI視頻輸入采集到原始幀進(jìn)入VPSS視頻處理子系統(tǒng)。VPSS根據(jù)需要輸出多路通道一路給編碼器做主碼流一路給編碼器做子碼流一路給VGS做縮放。VGS輸出一個(gè)低分辨率NV12或灰度幀供用戶態(tài)讀取。檢測(cè)線程通過(guò)Frame接口獲取該通道幀執(zhí)行遮擋統(tǒng)計(jì)和運(yùn)動(dòng)差分。這么做的好處是檢測(cè)分辨率固定且很小內(nèi)存帶寬開(kāi)銷低即使主碼流是4K、1080P檢測(cè)鏈路依然可以穩(wěn)定跑在D1甚至CIF級(jí)別。而且檢測(cè)鏈路獨(dú)立于編碼器主碼流編碼出問(wèn)題、斷幀不會(huì)卡死檢測(cè)線程。需要注意VGS通道的綁定關(guān)系、是否共享VPSS輸出、是否參與幀率控制這些都要根據(jù)你手里的SDK版本去配。我的經(jīng)驗(yàn)是如果平臺(tái)支持“獨(dú)立VGS縮放組”就新建一個(gè)分組不要夾在VPSS和編碼器中間去改主鏈路結(jié)構(gòu)否則很容易動(dòng)一處壞一路。2.2 檢測(cè)幀的分辨率與幀率怎么定檢測(cè)幀不是越大越好也不是幀率越高越好。這里有一個(gè)性價(jià)比平衡點(diǎn)。分辨率方面遮擋檢測(cè)需要統(tǒng)計(jì)邊緣和方差分辨率太低會(huì)把細(xì)節(jié)抹掉導(dǎo)致誤判運(yùn)動(dòng)檢測(cè)需要捕捉移動(dòng)目標(biāo)分辨率太低會(huì)導(dǎo)致小目標(biāo)漏檢。我實(shí)測(cè)下來(lái)的經(jīng)驗(yàn)區(qū)間場(chǎng)景類型推薦檢測(cè)分辨率推薦幀率用戶態(tài)CPU占用約固定攝像頭、室內(nèi)靜態(tài)場(chǎng)景CIF352x2885~10fps可忽略室外周界、行人走動(dòng)D1704x57610fps3%~5%大范圍區(qū)域、小目標(biāo)檢測(cè)720P裁剪區(qū)域12~15fps8%~12%幀率并非越高越好。因?yàn)檫\(yùn)動(dòng)檢測(cè)用幀差法把連續(xù)兩幀的差分作為“運(yùn)動(dòng)能量”來(lái)源幀率太高時(shí)相鄰幀之間的位移量很小反而對(duì)低速運(yùn)動(dòng)不敏感幀率太低又會(huì)漏掉快速移動(dòng)的目標(biāo)。5~10fps在實(shí)際工程里效果已經(jīng)不錯(cuò)同時(shí)還能兼顧C(jī)PU占用。如果場(chǎng)景中對(duì)告警延時(shí)要求很嚴(yán)比如門禁周界希望200ms內(nèi)出告警那幀率至少得12fps以上同時(shí)要把觸發(fā)幀數(shù)從連續(xù)3幀降到2幀。這個(gè)聯(lián)動(dòng)關(guān)系在調(diào)參時(shí)要想清楚。2.3 ROI區(qū)域與坐標(biāo)換算遮擋檢測(cè)和運(yùn)動(dòng)檢測(cè)都需要支持區(qū)域配置。用戶配置的ROI通常是在顯示畫面上的絕對(duì)像素坐標(biāo)而檢測(cè)算法內(nèi)部往往是網(wǎng)格坐標(biāo)或歸一化坐標(biāo)兩者必須做換算。我推薦的一種做法把畫面均勻劃分成M行N列的網(wǎng)格每個(gè)網(wǎng)格稱為一個(gè)Block。用戶配置矩形區(qū)域時(shí)將矩形坐標(biāo)按檢測(cè)幀寬高做歸一化left x / frame_widthtop y / frame_height。檢測(cè)結(jié)果輸出時(shí)再把命中的Block索引換算回顯示坐標(biāo)x block_col * block_widthy block_row * block_height。這里最容易出的問(wèn)題是用戶配置界面顯示的是OSD疊加后的坐標(biāo)而OSD層可能帶偏移或縮放。如果發(fā)現(xiàn)畫框位置總是偏一點(diǎn)優(yōu)先檢查用戶使用的坐標(biāo)系到底是顯示通道分辨率還是檢測(cè)通道分辨率。尤其當(dāng)設(shè)備做了電子放大、畫面裁剪時(shí)坐標(biāo)基準(zhǔn)必須換成裁剪后畫面否則區(qū)域會(huì)整體偏移。還有一點(diǎn)容易被忽略ROI區(qū)域邊緣的Block要不要參與檢測(cè)我的處理方式是不參與。因?yàn)椴糠諦lock落在ROI外差分統(tǒng)計(jì)混入非關(guān)注區(qū)域的運(yùn)動(dòng)會(huì)干擾事件判斷。網(wǎng)格遍歷時(shí)先做一次區(qū)域判定Block中心點(diǎn)不在ROI內(nèi)就跳過(guò)。3. 視頻遮擋檢測(cè)的原理、參數(shù)與防誤報(bào)3.1 遮擋檢測(cè)的計(jì)算原理遮擋檢測(cè)本質(zhì)上是一套圖像質(zhì)量評(píng)估指標(biāo)我通常提取三個(gè)統(tǒng)計(jì)量亮度均值Mean整幀Y分量的平均值。正常畫面均值通常在50~180之間8bit位深遮擋過(guò)暗時(shí)均值極低過(guò)曝遮擋時(shí)均值很高。亮度方差Variance反映畫面灰階分布的離散程度。畫面被遮擋后變得均勻方差會(huì)明顯變小正常有內(nèi)容畫面的方差通常在數(shù)百到上千。邊緣像素占比EdgeRatio用簡(jiǎn)單算子提取邊緣點(diǎn)數(shù)量占總數(shù)比例。遮擋后邊緣點(diǎn)大量減少正常畫面邊緣占比約為5%~15%。檢測(cè)邏輯非常簡(jiǎn)單每幀計(jì)算這三個(gè)統(tǒng)計(jì)量如果亮度均值超出正常范圍或者方差低于下限或者邊緣占比低于下限則判定為“異常幀”。但單幀判定不可靠必須結(jié)合連續(xù)幀計(jì)數(shù)。下面是一個(gè)簡(jiǎn)化的實(shí)現(xiàn)框架我習(xí)慣用C寫便于嵌入到MPP采集線程里typedef struct { int mean; int variance; int edge_ratio; } DetectStat; int check_blocked_frame(DetectStat *stat, BlockThreshold *thr) { if (stat-mean thr-mean_low || stat-mean thr-mean_high) { return 1; } if (stat-variance thr-var_low) { return 1; } if (stat-edge_ratio thr-edge_low) { return 1; } return 0; }實(shí)際使用中建議不要只用一個(gè)條件因?yàn)閱我粭l件誤報(bào)率很高。比如夜晚畫面亮度低是正常的只看均值會(huì)誤判墻壁反光場(chǎng)景方差也不高只看方差也會(huì)誤判。我處理時(shí)采用“加權(quán)投票”三個(gè)條件命中兩個(gè)及以上才認(rèn)為當(dāng)前幀異常這樣一個(gè)維度受噪聲影響時(shí)其他維度還能拉回來(lái)。3.2 關(guān)鍵閾值參數(shù)與靈敏度配置遮擋檢測(cè)的閾值參數(shù)通常不直接暴露給用戶而是通過(guò)“靈敏度”檔位映射。平臺(tái)SDK一般提供低、中、高三檔底層對(duì)應(yīng)不同的閾值組合。我整理過(guò)一組比較通用的映射關(guān)系可以作為起步值檔位亮度均值下限亮度均值上限方差下限邊緣占比下限適用場(chǎng)景低靈敏度402008008%明亮室內(nèi)、畫面穩(wěn)定中靈敏度302205005%室外多變場(chǎng)景高靈敏度202353003%昏暗環(huán)境、夜視場(chǎng)景這組值不是固定的。我會(huì)把閾值全部暴露成調(diào)試參數(shù)通過(guò)配置文件下發(fā)這樣現(xiàn)場(chǎng)調(diào)試時(shí)不用重新編譯固件直接改配置就能收斂誤報(bào)漏報(bào)。除了閾值本身“判定窗口”也很關(guān)鍵。我會(huì)在連續(xù)5~10幀異常后才上報(bào)遮擋事件避免畫面抖動(dòng)、飛蟲飛過(guò)瞬間造成誤報(bào)。如果把連續(xù)觸發(fā)幀數(shù)設(shè)成1基本沒(méi)法用隨便一個(gè)快速變亮的車燈就能觸發(fā)。3.3 光照突變與夜間模式的防誤報(bào)策略遮擋檢測(cè)最容易誤報(bào)的場(chǎng)景不是真遮擋而是光照突變。開(kāi)門一瞬間強(qiáng)光進(jìn)入畫面亮度均值從50跳到200方差和邊緣比例短暫失真如果閾值和判定窗口不合理就會(huì)上報(bào)“遮擋”。還有紅外切換的瞬間畫面可能從彩色變黑白亮度整體變化也容易誤報(bào)。我踩過(guò)坑之后總結(jié)出三個(gè)防誤報(bào)手段第一增加遲滯機(jī)制。進(jìn)入遮擋狀態(tài)使用較寬松的閾值A(chǔ)退出遮擋狀態(tài)使用更嚴(yán)苛的閾值B。也就是說(shuō)同樣一個(gè)畫面特征要讓算法“進(jìn)去容易出來(lái)難”。例如進(jìn)入時(shí)要求連續(xù)6幀均值低于30退出時(shí)要求連續(xù)10幀均值高于50。這樣做可以避免畫面在黑與稍黑之間反復(fù)橫跳告警狀態(tài)也穩(wěn)定。第二跳過(guò)自動(dòng)曝光收斂期。在檢測(cè)線程里加一個(gè)時(shí)間戳記錄當(dāng)檢測(cè)到曝光參數(shù)增益、快門發(fā)生大幅調(diào)整時(shí)暫時(shí)停止遮擋判定幾百毫秒等畫面重新穩(wěn)定后再繼續(xù)。如果SDK拿不到曝光參數(shù)可以退一步當(dāng)前幀與上一幀的亮度均值差超過(guò)30時(shí)就跳過(guò)本幀判定。這個(gè)辦法在實(shí)測(cè)中非常有用。第三夜間模式單獨(dú)匹配?!耙归g畫面亮度低、方差低”是正常狀態(tài)而不是遮擋。所以夜間不能直接套用日天的低閾值。我的做法是當(dāng)檢測(cè)到畫面均值整體低于40時(shí)自動(dòng)切換到夜間閾值組把亮度均值下限降到10方差下限降到150邊緣占比下限降到2%同時(shí)把判定窗口從5幀加到10幀。4. 運(yùn)動(dòng)檢測(cè)實(shí)現(xiàn)幀差、網(wǎng)格與事件上報(bào)4.1 幀間差分與運(yùn)動(dòng)能量運(yùn)動(dòng)檢測(cè)最經(jīng)典、也最實(shí)用的辦法是幀間差分。把當(dāng)前幀和上一幀做像素級(jí)減法計(jì)算差值絕對(duì)值差值大的區(qū)域就說(shuō)明“畫面發(fā)生了變化”。這個(gè)變化既可能是物體移動(dòng)也可能是光照變化、攝像頭抖動(dòng)所以要靠網(wǎng)格統(tǒng)計(jì)和閾值做進(jìn)一步過(guò)濾。實(shí)際計(jì)算時(shí)我不會(huì)直接對(duì)YUV全幀做逐像素差分而是把檢測(cè)幀先轉(zhuǎn)成8bit灰度也就是取Y分量然后按Block為單位統(tǒng)計(jì)平均絕對(duì)差分值。每個(gè)Block的差分能量計(jì)算方式diff_energy(block) sum(|current_pixel - reference_pixel|) / block_size這里的reference可以是上一幀也可以是更穩(wěn)定的背景幀。簡(jiǎn)單幀差的缺點(diǎn)是運(yùn)動(dòng)稍微慢一點(diǎn)、物體停在原地幾秒幀差就歸零所以很多項(xiàng)目里會(huì)維護(hù)一個(gè)長(zhǎng)時(shí)間平均值作為背景。不過(guò)在MPP平臺(tái)上跑簡(jiǎn)單的背景建模會(huì)增加內(nèi)存和CPU開(kāi)銷而且現(xiàn)場(chǎng)光照適應(yīng)性更差。我的經(jīng)驗(yàn)是先做上一幀差分配合“運(yùn)動(dòng)能量累計(jì)”機(jī)制效果已經(jīng)能滿足大部分布防需求。運(yùn)動(dòng)能量累計(jì)的思路是如果某個(gè)Block連續(xù)幾幀都有低強(qiáng)度差分視為累積運(yùn)動(dòng)如果某幀出現(xiàn)高強(qiáng)度差分視為瞬時(shí)運(yùn)動(dòng)。兩者通過(guò)不同閾值處理。這樣可以兼顧快速闖入和緩慢接近兩種場(chǎng)景。4.2 網(wǎng)格分割、靈敏度與觸發(fā)機(jī)制檢測(cè)區(qū)域通常劃分為網(wǎng)格而不是逐像素輸出。網(wǎng)格的常見(jiàn)規(guī)格有16x12、16x8、12x8具體選哪種取決于檢測(cè)分辨率和最小目標(biāo)尺寸。以D1分辨率704x576為例如果分12x8網(wǎng)格每個(gè)Block約為58x72像素。一個(gè)成年人站在15米外畫面中大概能占2x3個(gè)Block勉強(qiáng)夠檢測(cè)如果目標(biāo)是貓、狗這類小動(dòng)物建議用16x12甚至更細(xì)的網(wǎng)格但代價(jià)是CPU占用上升、容易被樹(shù)葉晃動(dòng)干擾。每個(gè)Block的差分結(jié)果與兩個(gè)閾值比較觸發(fā)閾值Motion Threshold差分能量超過(guò)該值才認(rèn)為該Block發(fā)生了明顯變化。去抖閾值Debounce Threshold低于該值則認(rèn)為沒(méi)有運(yùn)動(dòng)用于濾除噪聲。靈敏度檔位本質(zhì)上就是調(diào)整這兩個(gè)閾值。同一段畫面閾值越低越容易觸發(fā)但也更容易把樹(shù)葉搖動(dòng)、光影變化當(dāng)成運(yùn)動(dòng)。觸發(fā)機(jī)制還必須解決“瞬時(shí)噪聲”問(wèn)題。我用的方案是單個(gè)Block連續(xù)2~3幀都超過(guò)觸發(fā)閾值才確認(rèn)該Block為激活塊。激活塊的數(shù)量達(dá)到總檢測(cè)塊的一定比例比如5%或者激活塊集中在某個(gè)ROI區(qū)域里才上報(bào)一次運(yùn)動(dòng)事件。事件上報(bào)后進(jìn)入靜默期N秒靜默期內(nèi)不再重復(fù)上報(bào)避免告警風(fēng)暴。4.3 事件上報(bào)、畫框與OSD聯(lián)動(dòng)運(yùn)動(dòng)檢測(cè)觸發(fā)后平臺(tái)上正常要做兩件事上報(bào)事件數(shù)據(jù)、聯(lián)動(dòng)顯示。事件數(shù)據(jù)最簡(jiǎn)單的格式是運(yùn)動(dòng)塊位圖bitmap或者矩形區(qū)域結(jié)構(gòu)體。我這里推薦上報(bào)“激活Block集合”而不是上報(bào)一個(gè)合并大矩形。因?yàn)樯蠈涌蛻舳四玫紹lock集合后可以自己決定畫框方式可以把相鄰Block合并成一個(gè)外接矩形也可以把每一塊都畫出來(lái)。如果只上報(bào)一個(gè)大矩形多目標(biāo)離散運(yùn)動(dòng)時(shí)框會(huì)非常大用戶體驗(yàn)很差。合并矩形時(shí)建議做一個(gè)形態(tài)學(xué)處理把孤立的、面積小于閾值的激活Block過(guò)濾掉然后把鄰近Block合并。否則畫面上會(huì)出現(xiàn)幾十個(gè)碎框看起來(lái)像打地鼠。OSD聯(lián)動(dòng)屬于錦上添花。設(shè)備端可以直接在編碼通道疊加一個(gè)半透明遮罩把激活Block對(duì)應(yīng)的區(qū)域用色塊標(biāo)注方便現(xiàn)場(chǎng)安裝人員調(diào)試。還有一個(gè)很實(shí)用的聯(lián)動(dòng)運(yùn)動(dòng)檢測(cè)觸發(fā)時(shí)在子碼流OSD上顯示最后一張運(yùn)動(dòng)觸發(fā)幀的抓拍圖這個(gè)功能在門鈴、貓眼類產(chǎn)品里經(jīng)常用。5. 調(diào)試技巧與常見(jiàn)問(wèn)題排查實(shí)錄5.1 抓檢測(cè)幀與統(tǒng)計(jì)日志分析調(diào)試遮擋和運(yùn)動(dòng)檢測(cè)最忌諱憑感覺(jué)調(diào)參。我強(qiáng)烈建議在檢測(cè)線程里加一個(gè)“統(tǒng)計(jì)值日志”開(kāi)關(guān)每幀打印亮度均值、方差、邊緣比例、最大塊差分能量、激活塊數(shù)量。通過(guò)觀察這些數(shù)值你能很快判斷是閾值問(wèn)題還是數(shù)據(jù)鏈路問(wèn)題。例如如果一幀畫面明明是正常的但均值日志突然從100跳到220那就要去查是不是自動(dòng)曝光亂跳如果均值、方差一直正常但激活塊數(shù)量很多那就要把檢測(cè)幀抓下來(lái)看看是不是有樹(shù)影晃動(dòng)。抓取檢測(cè)幀本身也是一門學(xué)問(wèn)。MPP平臺(tái)一般支持把某個(gè)通道的YUV幀轉(zhuǎn)成RAW文件我通常用以下方式直接把VGS縮放后的檢測(cè)幀 dump 成YUV文件。用工具把YUV轉(zhuǎn)成PNG看畫面內(nèi)容。同時(shí)把對(duì)應(yīng)的統(tǒng)計(jì)值一起打印和圖像內(nèi)容對(duì)照。這么做最大的好處是你能確認(rèn)“算法看到的畫面”和“你腦子里以為的畫面”是不是同一個(gè)。我遇到過(guò)很多次主機(jī)畫面正常但檢測(cè)幀因?yàn)榭s放鏈路配置不對(duì)輸出全是黑的算法自然誤報(bào)遮擋。5.2 典型問(wèn)題速查表實(shí)際項(xiàng)目里常見(jiàn)問(wèn)題翻來(lái)覆去就那幾個(gè)我整理成速查表遇到類似現(xiàn)象可以先對(duì)照檢查問(wèn)題現(xiàn)象可能原因解決思路頻繁上報(bào)遮擋閾值過(guò)于激進(jìn)調(diào)整方差下限和邊緣占比下限增加連續(xù)判定幀數(shù)遮擋后很久才上報(bào)判定窗口太長(zhǎng)或檢測(cè)幀率太低縮短連續(xù)幀數(shù)提高檢測(cè)幀率到10fps以上遮擋解除后仍處于遮擋狀態(tài)遲滯退出條件過(guò)嚴(yán)降低退出閾值縮短退出判定幀數(shù)夜間誤報(bào)遮擋直接套用了白天閾值增加夜間模式閾值組降低對(duì)亮度和方差的要求運(yùn)動(dòng)檢測(cè)頻繁誤報(bào)網(wǎng)格太細(xì)、閾值太低增大觸發(fā)閾值增加連續(xù)觸發(fā)幀數(shù)調(diào)整靈敏度檔位運(yùn)動(dòng)檢測(cè)漏報(bào)低速目標(biāo)幀率太高導(dǎo)致幀差過(guò)小適當(dāng)降低檢測(cè)幀率或者使用背景累計(jì)法替代幀差法ROI畫框偏移坐標(biāo)基準(zhǔn)使用了編碼分辨率而非檢測(cè)分辨率統(tǒng)一換算到檢測(cè)幀坐標(biāo)系考慮電子放大和裁剪因素告警風(fēng)暴缺少事件去抖和靜默期增加靜默期合并激活Block按ROI過(guò)濾事件CPU占用偏高檢測(cè)分辨率過(guò)大或逐像素計(jì)算量大把檢測(cè)幀降到CIF/D1灰度化后計(jì)算開(kāi)啟NEON優(yōu)化5.3 性能優(yōu)化方法如果想在低端平臺(tái)上把CPU占用壓到最低有幾個(gè)非常實(shí)用的辦法。第一個(gè)辦法是“降分辨率再做差分”。不要直接拿主碼流的YUV做運(yùn)動(dòng)檢測(cè)先用VGS把分辨率降到CIF甚至更低。分辨率每降一半像素量降到四分之一計(jì)算量急劇減少。實(shí)測(cè)把1080P降到CIF差分計(jì)算耗時(shí)可以降到一個(gè)數(shù)量級(jí)。第二個(gè)辦法是“算灰度不做色度”。運(yùn)動(dòng)檢測(cè)和遮擋檢測(cè)都只需要Y分量。從NV12里面取Y平面非常方便因?yàn)閅數(shù)據(jù)在內(nèi)存前部連續(xù)存放直接取指針即可不需要單獨(dú)做色彩空間轉(zhuǎn)換。如果平臺(tái)輸出是YUV420SP正好Y就是那段連續(xù)緩沖。第三個(gè)辦法是“分可執(zhí)行塊并行”。檢測(cè)幀按Block粒度切分后多核并行計(jì)算。C語(yǔ)言里簡(jiǎn)單用多線程每個(gè)線程處理一行或若干行Block基本上可以吃滿多核。注意線程數(shù)和Block數(shù)要匹配Block太少時(shí)拆線程反而增加調(diào)度開(kāi)銷。第四個(gè)辦法是“限制檢測(cè)幀率”。遮擋檢測(cè)可以每2~3幀跑一次統(tǒng)計(jì)運(yùn)動(dòng)檢測(cè)才需要保持較高幀率。功能分化后CPU占用自然降下來(lái)。還有一個(gè)小技巧檢測(cè)幀的獲取盡量用“同步讀取、拷貝到本地緩存”的方式。不要在檢測(cè)線程里直接拿著平臺(tái)SDK的緩沖指針跑長(zhǎng)計(jì)算否則會(huì)導(dǎo)致VPSS通道緩沖無(wú)法及時(shí)歸還嚴(yán)重的會(huì)阻塞整個(gè)視頻流水線。正確做法是拿到幀后先memcpy到自己的內(nèi)存池然后立刻釋放平臺(tái)緩沖。這個(gè)細(xì)節(jié)在很多項(xiàng)目里被反復(fù)踩坑值得優(yōu)先注意。寫在最后做這塊功能的時(shí)候我最大的體會(huì)是遮擋檢測(cè)和運(yùn)動(dòng)檢測(cè)都不是“算法多高深”的活而是“工程細(xì)節(jié)多扎手”的活。平臺(tái)數(shù)據(jù)鏈路、坐標(biāo)換算、曝光變化、閾值遲滯每一項(xiàng)都比想象中更能影響最終效果。先把低分辨率檢測(cè)幀這一路打通把統(tǒng)計(jì)值和差分能量日志打清楚再把靈敏度、判定窗口、去抖靜默這些參數(shù)做成可調(diào)試配置項(xiàng)剩下的事情就是現(xiàn)場(chǎng)微調(diào)了。最后分享一個(gè)小技巧驗(yàn)收測(cè)試時(shí)不要只在辦公桌前面測(cè)幾眼就下結(jié)論。準(zhǔn)備幾段典型場(chǎng)景錄像循環(huán)播放分別覆蓋白天強(qiáng)光、夜間紅外、逆光、鏡頭臟污、高速運(yùn)動(dòng)、長(zhǎng)時(shí)間靜止這些情況然后反復(fù)觀察誤報(bào)和漏報(bào)。我當(dāng)時(shí)就是靠這種“錄像回放參數(shù)實(shí)時(shí)調(diào)節(jié)”的流程把一次很難纏的現(xiàn)場(chǎng)誤報(bào)問(wèn)題從懷疑算法故障縮小到“自動(dòng)曝光收斂期間閾值過(guò)緊”這一個(gè)配置項(xiàng)上。等你把這些基礎(chǔ)功打牢后面再往里疊加人形檢測(cè)、越界檢測(cè)這類重模型就輕松多了。