Python >>> 基于UDP 协议的实时网络视频传输
一、前言
最近想寫一個實時的視頻傳輸程序,然后上網找了很久沒有找到合適的
我想用OpenCV 進行圖像采集,然后用pygame 將視頻信號轉化為可通過UDP 網絡傳輸?shù)淖址?#xff0c;然后到達終端后再通過pygame 對字符流進行解析,進而將圖像顯示出來
之所以使用UDP 傳輸而不是TCP 傳輸,是因為UDP 在視頻傳輸方面擁有快速、無需連接等優(yōu)點,適合密集傳送大量信息的場合
但UDP 傳輸有一個問題,就是一次傳輸量有限,這就直接導致后續(xù)傳輸?shù)囊曨l信號需要進行一定壓縮
所以我就開始自己搗鼓了 😃
本文內容若有不懂可查閱如下教程:
Windows 安裝pygame 模塊
樹莓派 與 Xbox360手柄 基于pygame 的一次邂逅
樹莓派Camera 的使用
【手把手教學—超簡單】樹莓派安裝OpenCV 3
Python + OpenCV 學習筆記(二)>>> 加載視頻流
Python >>> UDP 網絡編程
我是用樹莓派作為視頻采集端,然后筆記本作為信號接收端的
注意:PC端需關閉防火墻后方可成功接收數(shù)據(jù)!
二、開始
1)整體思路
2)攝像頭采集視頻幀
import cv2 as cvcapture = cv.VideoCapture(0) while True:# 獲得圖像幀ret, frame = capture.read()# 圖像翻轉frame = cv.flip(frame, -1)# 將圖像尺寸縮小,便于傳輸frame = cv.resize(frame, (160, 120))3)將圖像幀輸出為圖片
cv.imwrite("test.jpg", frame)4)將圖片轉化為字符流
# 加載圖片 Img = pygame.image.load('/home/pi/test.jpg') # 圖片轉化字符串 string = pygame.image.tostring(Img, "RGB")5)通過UDP 傳輸字符流
我創(chuàng)建了一個進程用于傳輸數(shù)據(jù):
def mythread(sock, data, addr):sock.sendto(data, addr)print("已發(fā)送 " + str(len(data)) + " bytes")sock.close()# socket.SOCK_DGRAM 代表是使用UDP協(xié)議 sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) t = threading.Thread(target=mythread, args=(sock, string, ('192.168.0.196', 9999))) t.start()注意:當發(fā)送密集數(shù)據(jù)時,如圖像數(shù)據(jù)等。需要控制圖像大小(例如160*120),不然發(fā)不出去。
6)接收端接收數(shù)據(jù)并解析
# 創(chuàng)建連接 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 綁定端口 s.bind(('192.168.0.196', 9999)) # 接收數(shù)據(jù) data, addr = s.recvfrom(60000)# 字符串再轉化為圖片 img = pygame.image.frombuffer(data, (180, 160), "RGB")7)將圖像顯示出來
# 窗口內設置白色底色和圖片,并更新顯示 gameDisplay.fill(WHITE) gameDisplay.blit(img, (0, 0)) pygame.display.update()三、完整程序
1)發(fā)送端
#coding:utf-8 import pygame import cv2 as cv from picamera import PiCamera import time import threading import socketpygame.init()# 傳輸視頻信號的UDP 連接進程 def mythread(sock, data, addr):sock.sendto(data, addr)print("已發(fā)送 " + str(len(data)) + " bytes")sock.close()def main():print("begin")start = time.clock()capture = cv.VideoCapture(0)while True:ret, frame = capture.read()frame = cv.flip(frame, -1)frame = cv.resize(frame, (160, 120))cv.imwrite("test.jpg", frame)# 加載圖片Img = pygame.image.load('/home/pi/test.jpg')# 圖片轉化字符串string = pygame.image.tostring(Img, "RGB")sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)t = threading.Thread(target=mythread, args=(sock, string, ('192.168.0.196', 9999)))t.start()if cv.waitKey(10) & 0xff == ord('q'):breakmain() cv.destroyAllWindows()2)接收端
#coding=utf-8 import socket import time import threading import pygame# 顏色 WHITE = (255,255,255) GREEN = ( 0, 255, 0) BLUE = ( 0, 0, 128) BLACK = ( 0, 0, 0)# 創(chuàng)建連接 s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 綁定端口 s.bind(('192.168.0.196', 9999))print('Waiting for connection...')pygame.init()# 設置標題 pygame.display.set_caption('UDP 視頻傳輸')# 開啟窗口 display_width = 300 display_height = 200 gameDisplay = pygame.display.set_mode((display_width,display_height))# 判斷是否結束pygame gamefinish = False # 幀率 frame_rate = 0# 通過字體文件獲得字體對象 fontObj = pygame.font.Font('C:/Windows/Fonts/comici.ttf', 20) # 配置要顯示的文字 textSurfaceObj = fontObj.render('FPS', True, BLACK, WHITE) # 獲得要顯示的對象的rect textRectObj = textSurfaceObj.get_rect() # 設置顯示對象的坐標 textRectObj.center = (200, 10)# 用于視頻顯示delay clock = pygame.time.Clock() # 用于幀率計算 start = time.perf_counter()while not gamefinish:for event in pygame.event.get():if event.type == pygame.QUIT:gamefinish = Trueprint(event)# 無數(shù)據(jù)接收則線程掛起,等待數(shù)據(jù)data, addr = s.recvfrom(60000)frame_rate = frame_rate + 1if time.perf_counter() - start > 1:start = time.perf_counter()# 配置要顯示的文字textSurfaceObj = fontObj.render(("FPS: " + str(frame_rate)), True, BLACK, WHITE)frame_rate = 0print('Received from %s:%s.' % addr)# 字符串再轉化為圖片img = pygame.image.frombuffer(data, (160, 120), "RGB")# 窗口內設置白色底色和圖片,并更新顯示gameDisplay.fill(WHITE)gameDisplay.blit(img, (0, 0))gameDisplay.blit(textSurfaceObj, textRectObj)pygame.display.update()clock.tick(60)pygame.quit()四、結果
在實際測試中,我發(fā)現(xiàn)160*120的分辨率對網絡要求較高,而當分辨率降為80*60時則效果好一點(幀率基本在30左右):
當然,這樣的話視頻窗口顯得很小。
我們可以在接收端對圖像進行放大:
(成像質量下降)
總結
以上是生活随笔為你收集整理的Python >>> 基于UDP 协议的实时网络视频传输的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 工作372-cookie和session
- 下一篇: python获取淘宝服务器时间的代码