OpenCV視頻流Python多線程處理方法詳細(xì)分析
前言
最近在功能性測(cè)試的過程中,需要在Python環(huán)境下用OpenCV讀取網(wǎng)絡(luò)攝像頭的視頻流,接著用目標(biāo)檢測(cè)器進(jìn)行視屏幀的后續(xù)處理。在測(cè)試過程中發(fā)現(xiàn)如果是單線程的情況,會(huì)出現(xiàn)比較嚴(yán)重的時(shí)延,如果目標(biāo)檢測(cè)模型稍微大一點(diǎn),像YOLOv4這類的,那么情況更加嚴(yán)重。
后面考慮到演示效果,從單線程改為了多線程,即單獨(dú)用一個(gè)線程實(shí)時(shí)捕獲視頻幀,主線程在需要時(shí)從子線程拷貝最近的幀使用即可。通過這樣的修改,不僅時(shí)延基本消失,整個(gè)流程的實(shí)時(shí)性也有相對(duì)的提升,可以說(shuō)是非常實(shí)用的技巧。
Python多線程編程
使用Python進(jìn)行多線程編程是較為簡(jiǎn)單的,Python的threading模塊封裝了相關(guān)的操作,通過編寫功能類繼承threading.Thread即可實(shí)現(xiàn)自己的邏輯。簡(jiǎn)單的代碼示例如下所示:
class myThread(threading.Thread):
def __init__(self, name=None):
super(myThread, self).__init__(name=name)
def run(self):
print('=> Thread %s is running ...' % self.name)
thread = myThread()
thread.start()
thread.join()上面的代碼簡(jiǎn)單展示了如何使用線程類:通過調(diào)用start()方法,線程實(shí)例開始在單獨(dú)的線程上下文中運(yùn)行自己的run()函數(shù)處理任務(wù),直到線程退出。在此期間,主線程可以繼續(xù)執(zhí)行任務(wù)。當(dāng)主線程任務(wù)執(zhí)行結(jié)束時(shí),主線程可通過設(shè)置全局狀態(tài)變量告知子線程退出,同時(shí)調(diào)用join()方法等待子線程運(yùn)行結(jié)束。
OpenCV視屏流的多線程處理
在上面例子的基礎(chǔ)上,可對(duì)簡(jiǎn)單的單線程處理流程進(jìn)行優(yōu)化,即將讀取視頻幀的部分單獨(dú)放在一個(gè)線程執(zhí)行,同時(shí)提供線程間同步、數(shù)據(jù)交互的支持,在主線程中運(yùn)行目標(biāo)檢測(cè)模型和后續(xù)處理流程,在需要時(shí)從讀取視頻幀的子線程獲取最近的幀進(jìn)行預(yù)處理、推理、后處理和可視化等操作。相關(guān)的示例代碼如下:
import numpy as np
import cv2
import threading
from copy import deepcopy
thread_lock = threading.Lock()
thread_exit = False
class myThread(threading.Thread):
def __init__(self, camera_id, img_height, img_width):
super(myThread, self).__init__()
self.camera_id = camera_id
self.img_height = img_height
self.img_width = img_width
self.frame = np.zeros((img_height, img_width, 3), dtype=np.uint8)
def get_frame(self):
return deepcopy(self.frame)
def run(self):
global thread_exit
cap = cv2.VideoCapture(self.camera_id)
while not thread_exit:
ret, frame = cap.read()
if ret:
frame = cv2.resize(frame, (self.img_width, self.img_height))
thread_lock.acquire()
self.frame = frame
thread_lock.release()
else:
thread_exit = True
cap.release()
def main():
global thread_exit
camera_id = 0
img_height = 480
img_width = 640
thread = myThread(camera_id, img_height, img_width)
thread.start()
while not thread_exit:
thread_lock.acquire()
frame = thread.get_frame()
thread_lock.release()
cv2.imshow('Video', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
thread_exit = True
thread.join()
if __name__ == "__main__":
main()在上面的代碼中,為確保資源訪問不受沖突,使用threading.Lock進(jìn)行保護(hù);主線程使用thread_exit全局狀態(tài)變量控制子線程的運(yùn)行狀態(tài)。稍微特別一點(diǎn)的是,thread_exit實(shí)際上控制著兩個(gè)線程的運(yùn)行狀態(tài),因?yàn)樵谏鲜龅奶幚砹鞒讨校瑑蓚€(gè)線程都擁有終止運(yùn)行流程的話語(yǔ)權(quán),故這樣的處理是合理的。
結(jié)語(yǔ)
實(shí)際上使用多線程并行處理任務(wù),最大程度地利用資源早已是老生常談的技巧,例如在服務(wù)器端,會(huì)開辟有專門的線程池用于處理隨時(shí)可能到來(lái)的請(qǐng)求,而在嵌入式通信終端上,也通常采用線程池的方式來(lái)處理收到的消息包,以盡可能提升實(shí)時(shí)性。雖然多線程的處理方式相較單線程而言要稍微復(fù)雜一些,但帶來(lái)的性能提升確是實(shí)打?qū)嵉?,所以還是很值得一試。
到此這篇關(guān)于OpenCV視頻流多線程處理方法詳細(xì)分析的文章就介紹到這了,更多相關(guān)OpenCV視頻流內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
softmax及python實(shí)現(xiàn)過程解析
這篇文章主要介紹了softmax及python實(shí)現(xiàn)過程解析,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-09-09
Python語(yǔ)音合成之第三方庫(kù)gTTs/pyttsx3/speech橫評(píng)(內(nèi)附使用方法)
Python是一種非常強(qiáng)大的腳本語(yǔ)言,可以用來(lái)實(shí)現(xiàn)各種復(fù)雜的應(yīng)用,其中之一就是文本轉(zhuǎn)語(yǔ)音,即把文字轉(zhuǎn)換成聲音來(lái)發(fā)出,下面這篇文章主要給大家介紹了關(guān)于Python語(yǔ)音合成之第三方庫(kù)gTTs/pyttsx3/speech橫評(píng)的相關(guān)資料,文中還介紹了詳細(xì)的使用方法,需要的朋友可以參考下2023-05-05
Python 3.8正式發(fā)布,來(lái)嘗鮮這些新特性吧
今天 Python3.8 發(fā)布啦,它是 Python2 終結(jié)前最后一個(gè)大版本,我們一起看看這個(gè)版本都添加了那些新功能和特性2019-10-10
python實(shí)現(xiàn)網(wǎng)站的模擬登錄
這篇文章主要介紹了python實(shí)現(xiàn)網(wǎng)站的模擬登錄的相關(guān)資料,通過自己構(gòu)造post數(shù)據(jù)來(lái)用Python實(shí)現(xiàn)登錄過程,需要的朋友可以參考下2016-01-01
對(duì)python創(chuàng)建及引用動(dòng)態(tài)變量名的示例講解
今天小編就為大家分享一篇對(duì)python創(chuàng)建及引用動(dòng)態(tài)變量名的示例講解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來(lái)看看吧2018-11-11
TensorFlow2中提供的幾種處理特征列的方法小結(jié)
本文主要介紹了TensorFlow2中提供的幾種處理特征列的方法小結(jié),主要介紹了6種方式,具有一定的參考價(jià)值,感興趣的可以了解一下2023-09-09
用Python的Tornado框架結(jié)合memcached頁(yè)面改善博客性能
這篇文章主要介紹了用Python的Tornado框架結(jié)合memcached頁(yè)面改善vLog性能,主要使用到了緩存來(lái)提升性能,需要的朋友可以參考下2015-04-04

