朱 磊,王 鑫,劉 屹,董新華
(1.西安工程大學電子信息學院,西安 710048;2.杭州感想科技有限公司,杭州 310052)
圖像視頻信息的采集傳輸是視頻監控系統中的重要組成部分,隨著經濟的快速發展,城市規模的迅速擴大,視頻監控系統也被廣泛應用于企業、學校、銀行、居民小區等場合[1-2]。隨著無線網絡技術的發展,圖像視頻信息的傳輸也從最初的有線傳輸變成為無線網絡傳輸[3]。針對自研發的電能質量問題模擬電源系統的運行狀態的實時監測,提出了一種基于樹莓派的無線WiFi(wireless fidelity)視頻采集傳輸方法。
目前,圖像視頻網絡傳輸的方式主要分為兩種:一是基于WiFi的無線網絡傳輸,使用WiFi網絡傳輸較為方便,許多嵌入式產品也可以使用無線網卡來連接WiFi網絡,使用較為方便;二是基于4G的無線網絡傳輸,雖然網速較快但由于是按流量計費,對于視頻傳輸來說價格相對較貴[4]。圖像視頻網絡傳輸常用的嵌入式操作系統中有Linux、Android、wince等,由于Linux是一款開放源代碼的操作系統且有性能高、穩定、內核精簡等優點[5]。而樹莓派操作系統是Linux操作系統,所以選用樹莓派[6-7]。基于樹莓派的無線WiFi視頻采集傳輸方法可以分為兩種:第一種方法是基于SD卡(secure digital memory card)轉存的視頻采集傳輸方法(記作方法一),其特點是采用H.264視頻編碼技術,將采集到的視頻先儲存到樹莓派的SD卡中,然后通過無線網絡傳輸到PC(personal computer)機上[8-9];第二種方法是基于OpenCV(open source computer vision library)的視頻采集傳輸方法(記作方法二),其特點是采用JPEG(joint photographic experts group)壓縮算法,將采集到的視頻進行壓縮之后通過無線網絡傳輸到PC機上[10]。
針對基于樹莓派的無線WiFi視頻采集傳輸方法存在的實時性差、傳輸速率慢的問題。現提出一種基于樹莓派的無線WiFi視頻采集傳輸方法,該方法使用Picamera采集視頻流,并且使用并行線程來處理獲取的視頻流,壓縮JPEG格式的網絡視頻流,最后向PC端發送JPEG格式的網絡視頻流。本文方法基本解決了實時性差、傳輸速率慢的問題。提出方法與基于SD卡轉存的視頻采集傳輸方法相比,具有更好的實時性,且解決了存儲空間占據較大的問題;與基于OpenCV的視頻采集傳輸方法(記作方法三)相比,畫質更加的清晰;與基于Picamera的視頻流采集傳輸方法相比,數據傳輸的速率更快,達到了較好的效果。
基于樹莓派的無線WiFi圖像采集傳輸模塊如圖1所示,可以分為三個部分:一是用樹莓派及官方的攝像頭,對目標的視頻進行采集;二是將采集到的視頻進行傳輸;三是在PC機上顯示采集到的視頻。該方法在硬件方面由樹莓派、路由器及PC機組成,軟件部分主要為Python編寫的客戶端和服務端以及Linux系統的環境配置等。

圖1 樹莓派視頻采集模塊示意圖
Python編程中提供了強大的網絡編程支持,網絡編程中的一個基本組件是套接字(Socket)。套接字是進程間通信的一種方式,與其他進程間通信的主要區別在于,套接字能夠實現不同主機間的進程間通信。套接字主要分為服務器套接字和客戶端套接字。客戶端與服務端各有一個Python程序,通過網絡連接,這些程序可以在不同的計算機通過套接字進行通信。創建服務器套接字后,讓其等待連接請求的到來,這樣套接字將在某個網絡地址處監聽,網絡地址就是由IP(internet protocol)地址和端口號組成的,直到客戶端套接字建立連接后,服務器端和客戶端才能進行通信。
基于SD卡轉存的視頻采集傳輸方法的主要特點是先將視頻儲存到SD卡中然后通過套接字傳輸到PC機端。方法具體是通過Python實現的,首先以PC機為服務端并實現其功能,創建套接字的時候可以指定三個參數:一是地址族,默認為Socket.AF_INET;二是流套接字或者數據報套接字,因為使用的是TCP(transmission control protocol)套接字,所以選取流套接字 Socket.SOCK_STREAM[10];三是協議,使用的時候默認值為0。然后用函數bind綁定本地信息,用listen來監聽特定的地址,這里監聽的地址為客戶端地址即樹莓派的IP地址。樹莓派為客戶端并實現其功能,使用攝像頭采集目標的視頻,并且先將視頻儲存到樹莓派的SD卡中,然后創建套接字,連接到服務器端。服務器端套接字監聽到后,就可以和樹莓派客戶端進行通信。之后再進行數據的傳輸,在傳輸之前對傳輸的視頻進行打包處理,定義打包規則以及定義文件頭信息(包含文件名和文件大小),首先發送頭部信息,然后檢查正常,開始處理文件并且讀取文件數據,最后由Socket提供的send()函數發送數據。在服務器端由Socket套接字提供的recv()函數首先接收客戶端發過來的頭部信息,然后解包得到的文件名和文件大小,并且處理文件名,使用strip刪除文件名中多余的空字符,最后接收文件。Python的套接字提供了兩個函數:send()和recv(),通過這兩個函數可以將在樹莓派采集到的視頻傳輸到PC機上。經過測試,這種方法將采集到的視頻儲存到SD卡,畫質雖然清晰,但是實時性較差且需要的存儲空間較多。
基于OpenCV的視頻采集傳輸方法,其特點就是采集到的圖像不用儲存到樹莓派的SD卡中,在采集的同時可以直接把圖像發送到PC端。首先實現PC機的客戶端的功能,客戶端連接端口后,發送需要協商的分辨率和幀數,使傳輸圖像的屬性一致,客戶端使用線程,對圖片進行收集,對收到的每一張圖片進行解碼,并利用OpenCV播放出來。然后實現樹莓派的服務器端的功能,先通過在服務器端利用OpenCV捕獲到視頻中的每一幀圖片,將這些圖片進行壓縮成JPEG格式,以便于傳輸,按照提前協商好的分辨率和幀數進行打包編碼傳輸,利用服務器端打開端口,在連接客戶端后,便可以在客戶端中捕獲到服務器端的每一幀圖片,即可實現服務器端與客戶端兩端的實時視頻傳輸。這種方法是以樹莓派為服務器端、PC機端為客戶端,由樹莓派端采集視頻后通過無線網絡傳輸到PC機端。具體的操作方法是在PC端建立一個Python文件,同樣的,在樹莓派端建立一個Python的文件,并設置采集分辨率為640×480,幀數設置為30。然后分別運行兩端的Python文件,在PC機端可以得到結果。客戶端和服務端工作流程圖如圖2所示。

圖2 客戶端和服務端流程圖
基于Picamera視頻流傳輸方法的特點是不用儲存到樹莓派的SD卡中,在緩存中可以直接把圖像視頻信息實時的發送到PC端。由于視頻的采集傳輸方法的本質是圖片的傳輸,而不是處理圖片,如果想處理每一幀圖片,最好的方法是通過拍攝一段視頻來解碼,然后使用OpenCV模塊從視頻中獲取每一幀的圖片,或者可以將獲取到的視頻,通過OpenCV模塊將其傳輸到其他的設備上去處理。雖然這種方法比較方便,但因為得到的視頻圖像不清晰,所以省去了OpenCV的采集傳輸視頻的功能,用Picamera模塊來代替OpenCV模塊。通過用Picamera模塊和IO模塊的搭配使用,得到了較好的結果。由于樹莓派的IO讀寫速度優先,其用法可以通過創建一個新的數據流,然后通過獨立線程來處理獲取的圖像流,通過套接字傳輸,達到實時傳輸的目的,處理和解碼的速度都較理想,并且得到的畫質也比較清晰。
首先實現樹莓派的客戶端功能,創建和初始化套接字,然后設置攝像頭的分辨率以及幀數并創建一個Socket的文件流,通過Picamera模塊中的 capture_continuous()方法設置use_video_port捕獲圖片并且將捕獲的一組圖片轉換為網絡數據流,最后發送JPEG格式的視頻流。在PC機服務端部分,首先創建和初始化套接字,接收客戶端發過來的視頻流,然后通過cv2實時顯示得到的視頻流。具體操作如下:在PC端建立一個Python文件,在樹莓派端建立Python文件,并設置采集分辨率為640×480,幀數設置為30。之后運行PC機服務器端的Python文件以及樹莓派端的Python文件。使用這個方法,PC機端將以10 frame/s左右的速度獲取一組640×480的圖片,服務端和客戶端接收流程圖如圖3所示。

圖3 服務端和客戶端接收流程圖
基于Picamera視頻流傳輸方法雖然是實時的,但是在實時傳輸的速率方面比較慢,存在一定缺陷。因此,為了得到一個更加理想的效果,在客戶端程序加入并行線程,通過使用線程將捕獲到的視頻流傳輸到服務器端,加入線程將更加高效的同時處理圖像的捕捉和傳輸,這種方法能夠達到 15 frame/s左右的速度來獲取數據流。下面對部分程序進行說明:在樹莓派端加入并行線程,net.write(struct.pack(′ def run(self): # 這是個并行運行的線程 while not self.terminated: # 等待圖像被寫入視頻流 if self.event.wait(1): try:with net_lk: net.write(struct.pack(’ net.flush() self.stream.seek(0) net.write(self.stream.read()) finally: self.stream.seek(0) self.stream.truncate() self.event.clear() # 將處理完的圖片加載到序列中 with pool_lk: pool.append(self) 圖4 服務端和客戶端接收流程圖 為了測試本設計的應用性,搭建了基于樹莓派系統的視頻采集和傳輸的測試平臺,并且針對項目電能質量問題模擬電源及測試系統進行電路圖像的采集和傳輸。硬件平臺需要用到樹莓派,CSI攝像頭以及PC機。樹莓派內的操作系統用的是raspbian官方系統及Python3、Python的編輯器,并且需要安裝cv2模塊、Picamera模塊及IO模塊,這些模塊和軟件共同構建了樹莓派端的開發環境。攝像頭選用的是樹莓派官方提供的攝像頭,該攝像頭具有價格便宜、占用內存少及使用方便等優點。PC機使用的是Windows系統。在軟件平臺搭建方面,PC機上需要安裝Python、OpenCV以及環境的配置等,在這里就不再贅述了。硬件平臺如圖5所示。 圖5 測試平臺 首先在測試前需要協定采集視頻的分辨率及其幀數,采集的分辨率設置為640×480,幀數設置為每秒30幀。方法一是基于SD卡轉存的視頻采集傳輸方法,此方法是先儲存到SD卡中,再用Socket套接字傳輸,在PC機端接收到視頻文件,并且通過第三方軟件打開視頻文件。方法二是基于OpenCV的視頻傳輸方法,此方法是把采集到的視頻的每一幀用套接字傳輸到PC機端,在PC機上接收的。方法三是基于Picamera視頻流傳輸方法,此方法是將采集到的視頻流,轉換成網絡視頻流傳輸到PC機端。提出的改進后的基于Picamera視頻流傳輸方法,為了更加高效地同時處理圖像的捕捉和傳輸,使用并增加了獨立的并行線程,提高了捕獲和傳輸的速度從而提高了效率。 在PC機端接收圖像的畫質方面:將上述3種方法分別提取如圖6(a)上的紅色區域塊進行清晰度比較,比較后區域效果如圖6(b)~圖6(i)所示。由圖6(b)~圖6(i)可知,方法一雖然清晰但是由于其先儲存再傳輸的特點,實時性不好,如圖6(b)、圖6(f)所示;方法二的畫質與其他圖的畫質相比,清晰度較差,如圖6(c)、圖6(g)所示;方法三的畫質比方法二好,且實時性比方法一好,如圖6(d)、圖6(h)所示;將本文方法與其余3種方法進行比較,結果顯示本文方法比方法一的實時好,比方法二的畫質好,且本文方法比其余3種方法的傳輸速率要高,如圖 6(e)、圖6(i)所示。 圖6 各方法的效果 針對上述方法圖像傳輸的速率方面如表1所示:方法一是基于SD卡轉存的視頻采集傳輸方法,其圖像傳輸速率在10 frame/s左右,方法二是基于OpenCV的視頻傳輸方法,其圖像傳輸速率在 10 frame/s左右,方法三是基于Picamera視頻流傳輸方法,其圖像傳輸速率在10 frame/s左右,提出的改進后的基于Picamera視頻流傳輸方法,對樹莓派端的程序進行了改進,使用了獨立的并行線程,從而提高了捕獲和傳輸的效率。在樹莓派端,可以檢測出傳輸速度在15 frame/s左右。由表1可知,前幾種方法改進之前的速率均是10 frame/s左右,但是本文方法速率可以達到15 frame/s左右甚至更高,方法的傳輸速率比較理想。 為了更加直觀地比較幾種方法的區別,做了批次的速率測量,并且計算出平均值,從表1中的各個方法的視頻傳輸速率對比,可以直觀的看出方法一的速率平均值為10.63 frame/s,方法二的速率平均值為10.88 frame/s,方法三的速率平均值 10.74 frame/s,改進后的方法的速率平均值為15.39 frame/s,由此可以得出結論,本文方法比改進之前的傳輸速率提高了接近1.5倍。 表1 各方法的視頻傳輸速率對比 提出一種基于樹莓派的無線WiFi視頻采集傳輸方法,硬件測試平臺由樹莓派、CSI攝像頭、PC機及路由器組成的,軟件方面使用了Python、OpenCV等軟件,共同組建了視頻采集和傳輸模塊。采用三種方法與本文方法進行比較,本文方法與基于SD卡轉存的視頻采集傳輸方法比較,具備更好的實時性;與基于OpenCV的視頻采集傳輸方法比較,畫質更加清晰;與基于Picamera視頻流采集傳輸方法相比,傳輸速率由原來的10 fps左右增加到了15 fps左右。通過使用基于樹莓派的無線WiFi視頻采集傳輸方法對視頻進行采集和傳輸,實現了視頻實時傳輸的功能。通過多次修改代碼,得到了比較理想的實驗效果。
4 測試平臺搭建及測試結果



5 結論