最近在幫導(dǎo)師做一個項目隅肥,需求要用Python做一個桌面軟件。如果做正式項目用tk肯定是不行的,所以第一個想到的就是PyQt5
這是我做了兩個月后挤忙,才知道,PyQt其實并不是Qt的官方Python支持谈喳。官方的Qt for python是PySide2册烈,這兩者在我使用上主要是Signal(信號槽)部分不太一樣,PySide2用的是和C++ Qt相似的語法結(jié)構(gòu)婿禽,而PyQt則用了自己的pyqtSignal赏僧,其他部分兩家都繼承了C++的接口,區(qū)別不是很大扭倾。
項目要用到攝像頭視頻監(jiān)控淀零,一開始我就想到了用QCamera,但怎么都開啟不了(可能是太菜了)后面進(jìn)度在催吆录,沒辦法用了第二種方案窑滞,OpenCV的cv2.Videocapture()。這下好了恢筝,給我整的生活不能自理哀卫,不知道cv2 Videocapture這個庫到底是怎么實現(xiàn)的,bug一堆不說撬槽,運行起來還各種閃退此改,不穩(wěn)定。最后不得不用了Capture Thread+ Fetch Thread的方案侄柔,即一個線程不停地去抓取攝像頭的數(shù)據(jù)幀共啃,另一個線程和主線程溝通,才勉強(qiáng)維持穩(wěn)定(中間還用了一堆Mutex同步線程暂题,頭發(fā)都要掉光)移剪。
但后來發(fā)現(xiàn),這樣做資源開銷大的離譜薪者。尤其是當(dāng)我們項目用到了4K分辨率的攝像頭時纵苛,主線程基本卡死不能動了(光一個攝像頭就占用了8核CPU的40%,這還是4GHz x86的CPU啊)項目還要用四個攝像頭攻人,這要跑起來難道得用服務(wù)器取试?
痛定思痛,就算cv2的解決方案維護(hù)了兩個月怀吻,也只能放棄瞬浓,轉(zhuǎn)頭認(rèn)真研究QCamera。
QCamera是Qt對于攝像設(shè)備的一個抽象蓬坡,所以它首先初始化需要鎖定一個攝像頭猿棉。這就需要QCameraInfo類提供系統(tǒng)中可用攝像頭的信息。
const?QList<QCameraInfo> cameras =QCameraInfo::availableCameras();
for (const?QCameraInfo&cameraInfo : cameras)?qDebug()?<< cameraInfo.deviceName();
然后屑咳,初始化QCamera铺根。
下面,要給QCamera找一個視頻輸出的區(qū)域QCameraViewFinder乔宿。QCamera支持QVideoWidget,QGraphicsVideoItem访雪,QAbstractVideoSurface三種接口详瑞,感興趣的小伙伴可以去了解一下區(qū)別。這三種在QtDesigner里都找不到臣缀,沒關(guān)系坝橡,我們可以在界面里先預(yù)留一個QGridLayout,用來動態(tài)添加view精置。
接下來计寇,就是保存圖片了。QCamera需要拍攝圖片脂倦,用的是QCameraImageCapture類番宁。這個類初始化用QCamera對象作為參數(shù),然后就可以進(jìn)行capture操作赖阻。但是capture必須寫入硬盤(我也不知道為什么蝶押,但是如果需要高性能或者快速拍攝,這個肯定行不通火欧,因為寫入硬盤是非常非常緩慢的棋电,甚至需要界面中添加等待提示,因為我們攝像頭4K拍出來有10MB苇侵,保存要十幾秒赶盔,這也是我認(rèn)為Qt做的不夠好的地方,為什么不能加一個capture到QImage的接口)但是好在項目剛好需要保存在本地榆浓。
這里有一個細(xì)節(jié)于未,因為capture()寫入硬盤和其他線程是異步的,你不能capture()完了立馬cam.stop(),否則會capture失敗沉眶。所以我加了個簡單的計數(shù)判斷打却,達(dá)到finish計數(shù)才stop。這個后面可以再改進(jìn)谎倔。
????到這里QCamera用法基本上就結(jié)束了柳击,可以看到Qt5雖然也有不足,但比起cv2.Videocapture還是做的好不少片习,Cpu占用率也下來了捌肴。