使用多線程加速實(shí)時(shí)視頻流處理的思路
再初次接觸機(jī)器視覺的小伙伴應(yīng)該都會遇到這種情況,明明攝像頭輸出的畫面是 30 fps 的,但對每一幀圖像進(jìn)行畸變矯正或者是一些圖像處理后,視頻幀數(shù)降低到了不到 10 fps!還伴隨出現(xiàn)丟幀或者是播放緩慢,內(nèi)存占用越來越多。
最近想到了一種利用線程池去并行處理視頻流的方法,該方法在處理耗時(shí)高于視頻幀產(chǎn)生間隔時(shí),能有效提高最終視頻輸出的幀率。本文會用偽代碼來描述整個(gè)方法的框架,不提供實(shí)際的代碼。
基本思路就是將讀取、計(jì)算和消費(fèi)三部分分離到不同的線程中,讀取視頻流的圖像為單獨(dú)一條線程,圖像處理的計(jì)算在線程池中進(jìn)行,最后使用結(jié)果的部分也是單獨(dú)一條線程。
下面開始介紹完整的流程細(xì)節(jié),先定義一些基本的接口和類型:
首先就是讀取圖像線程的部分,該線程負(fù)責(zé)讀取一幀視頻圖像,然后創(chuàng)建一個(gè)圖像處理任務(wù)提交到線程池中,圖像處理完成后,把結(jié)果塞到優(yōu)先隊(duì)列里。
消費(fèi)結(jié)果的線程邏輯會稍微復(fù)雜一點(diǎn),因?yàn)榫€程池中執(zhí)行任務(wù)的順序是不確定,我們需要用條件變量來控制輸出順序。
## 總結(jié)
整個(gè)框架的思路其實(shí)挺簡單的,但實(shí)際實(shí)現(xiàn)的時(shí)候需要注意的細(xì)節(jié)會比較多,這里舉例兩個(gè):
1. 多線程的安全問題,用 C/C++ 實(shí)現(xiàn)的時(shí)候,要盡可能避免圖像數(shù)據(jù)的拷貝,又要保證線程池任務(wù)執(zhí)行和最后讀取結(jié)果的時(shí)候圖像數(shù)據(jù)是有效的;
2. 最終使用結(jié)果圖像的部分,由于是并行處理多幀圖像,最終得到圖像的頻率是不穩(wěn)定的,有可能一瞬間就讀讀到 N 幅圖像,這時(shí)候就需要根據(jù)需求來修改代碼了,例如我最終的圖像是要實(shí)時(shí)顯示出來,那就要加上合適的延遲再播放下一幀,不如畫面就會出現(xiàn)卡頓一下下,然后瞬間播放好幾幀的情況;