用python通过opencv模块来做实时监控这件事情很早就想做了,但是因为本人的拖延症一直被搁置直到最近强迫自己才通过网上的现有资料进行进行更改,完成了这个基本能正常工作的版本,我们暂且叫他1.0
首先是服务器端代码,主要功能其实就是通过opencv模块进行摄像头数据的采集,然后将每一帧数据,也就是图像,通过cv2.imencode()函数转换成jpg格式,这个步骤主要是为了将数据进行压缩,不然传输的数据量太大,我们通常外网访问基本没法承受。(假设我们不去进行任何数据压缩处理,那一个380240的图片实际上是3804203(这个3是因为是RGB图)个字节,也就是470kb,一秒就算只有10帧,那也至少需要4.7MB每秒的传输速度。那显然不靠谱。)压缩完之后,然后通过socket模块使用tcp协议将数据发送出去,服务器端程序基本面功能也就完成了。
服务器端代码:
客户端代码,主要使用socket模块通过tcp协议将服务器发来的数据进行解码,然后显示在自己的电脑上,由于本人极端厌恶做人机交互界面,所以这里通过配置文件的形式来改变整个监控的参数,比如每秒几帧,图像分辨率,图像质量,还有服务器ip。首次运行,系统会自动创建配置文件,txt格式,然后将配置文件里的数据改成你需要的数据再保存,再次运行程序,程序会自动读取你最新配置的配置参数。
客户端代码:
import socket;
import threading;
import struct;
import cv2
import time
import os
import numpy
class webCamera:
def __init__(self, resolution = (640, 480), host = ("", 7999)):
self.resolution = resolution;
self.host = host;
self.setSocket(self.host);
self.img_quality = 15
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 recv_config(self,client):
info = struct.unpack("lhh",client.recv(8));
if info[0]>911: #print(info[0])
self.img_quality=int(info[0])-911
self.resolution=list(self.resolution)
self.resolution[0]=info[1]
self.resolution[1]=info[2]
self.resolution=tuple(self.resolution)
return 1
else :
return 0
def _processConnection(self, client,addr):
if(self.recv_config(client)==0):
return
camera = cv2.VideoCapture(0)
encode_param=[int(cv2.IMWRITE_JPEG_QUALITY),self.img_quality]
f = open("video_info.txt", 'a+')
print("Got connection from %s:%d" % (addr[0], addr[1]),file=f);
print("像素为:%d * %d"%(self.resolution[0],self.resolution[1]),file=f)
print ("打开摄像头成功",file=f)
print("连接开始时间:%s"%time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(time.time())),file=f)
f.close()
while(1):
time.sleep(0.13)
(grabbed, self.img) = camera.read()
self.img = cv2.resize(self.img,self.resolution)
result, imgencode = cv2.imencode('.jpg',self.img,encode_param)
img_code = numpy.array(imgencode)
self.imgdata = img_code.tostring()
try:
client.send(struct.pack("lhh",len(self.imgdata),
self.resolution[0],self.resolution[1])+self.imgdata); #发送图片信息(图片
长度,分辨率,图片内容)
except:
f = open("video_info.txt", 'a+')
print("%s:%d disconnected!" % (addr[0], addr[1]),file=f);
print("连接结束时间:%s"%time.strftime("%Y-%m-%d %H:%M:%S",
time.localtime(time.time())),file=f)
print("****************************************",file=f)
camera.release()
f.close()
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();
客户端代码,主要使用socket模块通过tcp协议将服务器发来的数据进行解码,然后显示在自己的电脑上,由于本人极端厌恶做人机交互界面,所以这里通过配置文件的形式来改变整个监控的参数,比如每秒几帧,图像分辨率,图像质量,还有服务器ip。首次运行,系统会自动创建配置文件,txt格式,然后将配置文件里的数据改成你需要的数据再保存,再次运行程序,程序会自动读取你最新配置的配置参数。
客户端代码:
import socket;
import threading;
import struct; import os;
import time; import sys;
import numpy
import cv2import re
class webCamConnect:
def __init__(self, resolution = [640,480], remoteAddress = ("115.216.215.130",
7999), windowName = "video"):
self.remoteAddress = remoteAddress;
self.resolution = resolution;
self.name = windowName;
self.mutex = threading.Lock();
self.src=911+15
self.interval=0
self.path=os.getcwd()
self.img_quality = 15
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 _processImage(self):
self.socket.send(struct.pack("lhh",self.src,self.resolution[0],self.resolution[1]));
while(1):
info = struct.unpack("lhh",self.socket.recv(8));
bufSize = info[0];
if bufSize:
try:
self.mutex.acquire();
self.buf=b''
tempBuf=self.buf;
while(bufSize): #循环读取到一张图片的长度
tempBuf = self.socket.recv(bufSize);
bufSize -= len(tempBuf);
self.buf += tempBuf;
data = numpy.fromstring(self.buf,dtype='uint8')
self.image=cv2.imdecode(data,1)
cv2.imshow(self.name,self.image)
except:
print("接收失败")
pass;
finally:
self.mutex.release();
if cv2.waitKey(10) == 27:
self.socket.close()
cv2.destroyAllWindows()
print("放弃连接")
break
def getData(self, interval):
showThread=threading.Thread(target=self._processImage);
showThread.start();
if interval != 0: # 非0则启动保存截图到本地的功能
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);
cv2.imwrite(path + "\\" + time.strftime("%Y%m%d-%H%M%S",
time.localtime(time.time())) + ".jpg",self.image)
except:
pass;
finally:
self.mutex.release();
time.sleep(interval);
def check_config(self):
path=os.getcwd()
print(path)
if os.path.isfile(r'%s\video_config.txt'%path) is False:
f = open("video_config.txt", 'w+')
print("w = %d,h = %d" %(self.resolution[0],self.resolution[1]),file=f)
print("IP is %s:%d" %(self.remoteAddress[0],self.remoteAddress[1]),file=f)
print("Save pic flag:%d" %(self.interval),file=f)
print("image's quality is:%d,range(0~95)"%(self.img_quality),file=f)
f.close()
print("初始化配置");
else:
f = open("video_config.txt", 'r+')
tmp_data=f.readline(50)#1 resolution
num_list=re.findall(r"\d+",tmp_data)
self.resolution[0]=int(num_list[0])
self.resolution[1]=int(num_list[1])
tmp_data=f.readline(50)#2 ip,port
num_list=re.findall(r"\d+",tmp_data)
str_tmp="%d.%d.%d.%d"
%(int(num_list[0]),int(num_list[1]),int(num_list[2]),int(num_list[3]))
self.remoteAddress=(str_tmp,int(num_list[4]))
tmp_data=f.readline(50)#3 savedata_flag
self.interval=int(re.findall(r"\d",tmp_data)[0])
tmp_data=f.readline(50)#3 savedata_flag
#print(tmp_data)
self.img_quality=int(re.findall(r"\d+",tmp_data)[0])
#print(self.img_quality)
self.src=911+self.img_quality
f.close()
print("读取配置")
def main():
print("创建连接...")
cam = webCamConnect();
cam.check_config()
print("像素为:%d * %d"%(cam.resolution[0],cam.resolution[1]))
print("目标ip为%s:%d"%(cam.remoteAddress[0],cam.remoteAddress[1]))
cam.connect();
cam.getData(cam.interval);
if __name__ == "__main__":
main();
网友评论