看了一個基於python的高速視頻傳輸程序發現挺有意思的。就自己仿照寫了一個,,,,
需要用到的擴展包有:
PIL(Pillow), 處理圖片
VideoCapture, 調用攝像頭截圖
Pygame 圖片的顯示
上面的擴展可以從http://www.lfd.uci.edu/~gohlke/pythonlibs/ 獲得
運行環境:Py3.3
服務端代碼:
from VideoCapture import Device;
import socket;
import threading;
import struct;
class webCamera:
def __init__(self, resolution = (640, 480), host = ("", 8000)):
self.resolution = resolution;
self.host = host;
self.video = Device();
self.setSocket(self.host);
def setImageResolution(self, resolution):
self.resolution = resolution;
def setHost(self, host):
self.host = host;
def setSocket(self, host):
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM);
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1);
self.socket.bind(self.host);
self.socket.listen(5);
print("Server running on port:%d" % host[1]);
def _processConnection(self, client,addr):
print("Got connection from %s:%d" % (addr[0], addr[1]));
while(1):
self.img = self.video.getImage();
self.imgdata = self.img.resize(self.resolution).tostring();
try:
client.send(struct.pack("lhh", len(self.imgdata), self.resolution[0], self.resolution[1]) + self.imgdata); #發送圖片信息(圖片長度,分辨率,圖片內容)
except ConnectionResetError:
print("%s:%d disconnected!" % (addr[0], addr[1]));
return;
def run(self):
while(1):
client,addr = self.socket.accept();
clientThread = threading.Thread(target = self._processConnection, args = (client, addr, )); #有客戶端連接時產生新的線程進行處理
clientThread.start();
def main():
cam = webCamera();
cam.run();
if __name__ == "__main__":
main();
客戶端代碼:
import pygame;
import socket;
import threading;
from PIL import Image;
import struct;
import os;
import time;
import sys;
class webCamConnect:
def __init__(self, resolution = (640, 480), remoteAddress = ("127.0.0.1", 8000), windowName = "Demo"):
self.remoteAddress = remoteAddress;
self.resolution = resolution;
self.name = windowName;
self.mutex = threading.Lock();
def _setSocket(self):
self.socket=socket.socket(socket.AF_INET, socket.SOCK_STREAM);
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1);
def connect(self):
self._setSocket();
self.socket.connect(self.remoteAddress);
def _initWindow(self):
pygame.init();
screen = pygame.display.set_mode(self.resolution);
pygame.display.set_caption(self.name);
return screen;
def _processImage(self):
screen = self._initWindow();
while(1):
info = struct.unpack("lhh",self.socket.recv(8));
bufSize = info[0];
if bufSize:
try:
self.mutex.acquire();
self.buf=bytes(0,"little");
tempBuf=self.buf;
while(bufSize): #循環讀取到一張圖片的長度
tempBuf = self.socket.recv(bufSize);
bufSize -= len(tempBuf);
self.buf += tempBuf;
self.image = pygame.image.frombuffer(self.buf, (info[1], info[2]), "RGB");
for event in pygame.event.get():
if event.type == pygame.QUIT:
return;
screen.blit(self.image, (0, 0));
pygame.display.update();
except:
pass;
finally:
self.mutex.release();
def getData(self, interval = -1):
showThread=threading.Thread(target=self._processImage);
showThread.start();
if interval != -1: # 非-1則啓動保存截圖到本地的功能
saveThread=threading.Thread(target=self._savePicToLocal,args = (interval, ));
saveThread.setDaemon(1);
saveThread.start();
def setWindowName(self, name):
self.name = name;
def setRemoteAddress(remoteAddress):
self.remoteAddress = remoteAddress;
def _savePicToLocal(self, interval):
while(1):
try:
self.mutex.acquire();
path=os.getcwd() + "\\" + "savePic";
if not os.path.exists(path):
os.mkdir(path);
image=Image.frombytes("RGB", self.resolution, self.buf);
image.save(path + "\\" + time.strftime("%Y%m%d-%H%M%S", time.localtime(time.time())) + ".jpg");
except:
pass;
finally:
self.mutex.release();
time.sleep(interval);
def main():
cam = webCamConnect();
cam.connect();
cam.getData();
if __name__ == "__main__":
main();
運行截圖:
服務端:
客戶端:(多個窗口)