Python远程视频监控程序的实例代码


Posted in Python onMay 05, 2019

老板由于事务繁忙无法经常亲临教研室,于是让我搞个监控系统,让他在办公室就能看到教研室来了多少人。o(>?<)o|||

最初我的想法是直接去网上下个软件,可是找来找去不是有毒就是收费,无奈技术不到家无法破解,只得另寻他法。

正当没有办法的时候,我看到一篇博文一个基于python的高速视频传输程序 ,看完茅塞顿开,觉得完全可以自己写一个,在此感谢作者詹姆斯。

这个程序包括一个服务器和一个客户端。需要的库有 VideoCapture 和 pygame,一个用来得到摄像头的视频,一个用来显示。Python库可以点这里下载:Python Extension Packages。进去后ctrl+F找到相应的库,然后选择相应的版本即可,这里还有很多其他的库可提供下载。

我想到的解决方案是,在教研室开一台电脑,接一个USB摄像头,然后开启一个服务器程序,等待着老板使用客户端连接,由于是实时视频传输,使用UDP协议。(主要传输部分采用詹姆斯的代码)。

服务器端代码如下:

# -*- coding: UTF-8 -*-
import socket
import time
import traceback
from VideoCapture import Device
import threading
# 全局变量
is_sending = False
cli_address = ('', 0)
# 主机地址和端口
host = ''
port = 10218
# 初始化UDP socket
ser_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
ser_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
ser_socket.bind((host, port))
# 接收线程类,用于接收客户端发送的消息
class UdpReceiver(threading.Thread):
 def __init__(self):
  threading.Thread.__init__(self)
  self.thread_stop = False
 def run(self):
  while not self.thread_stop:
   # 声明全局变量,接收消息后更改
   global cli_address 
   global is_sending
   try:
    message, address = ser_socket.recvfrom(2048)
   except:
    traceback.print_exc()
    continue
  #  print message,cli_address
   cli_address = address
   if message == 'startCam':
    print 'start camera',
    is_sending = True
    ser_socket.sendto('startRcv', cli_address)    
   if message == 'quitCam':
    is_sending = False
    print 'quit camera',
 def stop(self):
  self.thread_stop = True
# 创建接收线程
receiveThread = UdpReceiver()
receiveThread.setDaemon(True)   # 该选项设置后使得主线程退出后子线程同时退出
receiveThread.start()
# 初始化摄像头
cam = Device()
cam.setResolution(320,240)
# 主线程循环,发送视频数据
while 1:
 if is_sending:  
  img = cam.getImage().resize((160,120))
  data = img.tostring()
  ser_socket.sendto(data, cli_address) 
  time.sleep(0.05)
 else:
  time.sleep(1)
receiveThread.stop()
ser_socket.close()

服务器启动一个子线程,来监听客户端发送的消息。当有消息时,将is_sending改为True,则服务器向该客户端发送视频数据。具体信息可以看代码注释。

客户端代码如下:

# -*- coding: UTF-8 -*-
import socket, time
import pygame
from pygame.locals import *
from sys import exit
# 服务器地址,初始化socket
ser_address = ('localhost', 10218)
cli_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
# 设置超时
cli_socket.settimeout(5)
# 向服务器发送消息,并判断接收时是否超时,若超时则重发
while 1:
 cli_socket.sendto('startCam', ser_address)
 try:
  message, address = cli_socket.recvfrom(2048)
  if message == 'startRcv':
   print message
   break
 except socket.timeout:
  continue
# 此句无用。。防止窗口初始化后等待数据
cli_socket.recvfrom(65536)
# 初始化视频窗口
pygame.init()
screen = pygame.display.set_mode((640,480))
pygame.display.set_caption('Web Camera')
pygame.display.flip()
# 设置时间,可以用来控制帧率
clock = pygame.time.Clock()
# 主循环,显示视频信息
while 1:
 try:
  data, address = cli_socket.recvfrom(65536)
 except socket.timeout:
  continue
 camshot = pygame.image.frombuffer(data, (160,120), 'RGB')
 camshot = pygame.transform.scale(camshot, (640, 480))
 for event in pygame.event.get():
  if event.type == pygame.QUIT:
   cli_socket.sendto('quitCam', ser_address)
   cli_socket.close()
   pygame.quit()
   exit()
 screen.blit(camshot, (0,0))
 pygame.display.update() 
 clock.tick(20)

客户端就是简单地向服务器发送启动消息,接收到回复后开始进入主循环开始接收视频数据并显示。

由于UDP协议不保证信息是否成功到达,因此前面设置了个重发机制,只有当客户端收到服务器的回复后,才停止发送开启消息并进入主循环。具体见注释。

使用时将localhost改成服务器IP即可,目前测试仅适用于局域网,校园网。外网暂未测试,熟悉网络编程的同学可以自行实验。

经验

调试的时候出现过服务器怎么都收不到客户端消息,结果调试一下午都找不到原因。晚上回来把防火墙、安全软件全关了,顺利通过。

服务器开启新线程后,由于Python奇怪的设定,主线程退出后子线程得完成后才会退出,而这里子线程又是一个死循环,因此需要对子线程调用setDaemon(True),这样主线程退出时子线程也会自动退出。若没有调用该方法,调试一次后第二次可能失败,因为后台还有个子线程在运行。

Python 相关文章推荐
python文件读写并使用mysql批量插入示例分享(python操作mysql)
Feb 17 Python
Python探索之pLSA实现代码
Oct 25 Python
python实现数据预处理之填充缺失值的示例
Dec 22 Python
Pandas 对Dataframe结构排序的实现方法
Apr 10 Python
Python实现数据可视化看如何监控你的爬虫状态【推荐】
Aug 10 Python
pandas把所有大于0的数设置为1的方法
Jan 26 Python
Python 多线程,threading模块,创建子线程的两种方式示例
Sep 29 Python
Python绘制三角函数图(sin\cos\tan)并标注特定范围的例子
Dec 04 Python
Django框架静态文件处理、中间件、上传文件操作实例详解
Feb 29 Python
keras 如何保存最佳的训练模型
May 25 Python
python学习笔记之多进程
Aug 06 Python
Python request post上传文件常见要点
Nov 20 Python
Python统计一个字符串中每个字符出现了多少次的方法【字符串转换为列表再统计】
May 05 #Python
20行python代码实现人脸识别
May 05 #Python
使用python实现mqtt的发布和订阅
May 05 #Python
Python向excel中写入数据的方法
May 05 #Python
python使用pandas处理大数据节省内存技巧(推荐)
May 05 #Python
python使用MQTT给硬件传输图片的实现方法
May 05 #Python
Python实现的插入排序,冒泡排序,快速排序,选择排序算法示例
May 04 #Python
You might like
PHP 解决session死锁的方法
2013/06/20 PHP
php调用c接口无错版介绍
2014/03/11 PHP
PHP的preg_match匹配字符串长度问题解决方法
2014/05/03 PHP
PHP下载生成的csv文件及问题总结
2015/08/06 PHP
php自定义函数实现二维数组按指定key排序的方法
2016/09/29 PHP
用PHP的反射实现委托模式的讲解
2019/03/22 PHP
JQuery Ajax通过Handler访问外部XML数据的代码
2010/06/01 Javascript
使用按钮控制以何种方式打开新窗口的属性介绍
2012/12/17 Javascript
javascript精确统计网站访问量实例代码
2015/12/19 Javascript
用canvas 实现个图片三角化(LOW POLY)效果
2016/02/18 Javascript
如何消除inline-block属性带来的标签间间隙
2016/03/31 Javascript
详解JSON1:使用TSQL查询数据和更新JSON数据
2016/11/21 Javascript
javascript 中null和undefined区分和比较
2017/04/19 Javascript
JS函数节流和函数防抖问题分析
2017/12/18 Javascript
Vue slot用法(小结)
2018/10/22 Javascript
vue中英文切换实例代码
2020/01/21 Javascript
Windows中使用wxPython和py2exe开发Python的GUI程序的实例教程
2016/07/11 Python
详解Python 数据库的Connection、Cursor两大对象
2018/06/25 Python
攻击者是如何将PHP Phar包伪装成图像以绕过文件类型检测的(推荐)
2018/10/11 Python
Python CSV文件模块的使用案例分析
2019/12/21 Python
python GUI库图形界面开发之PyQt5结合Qt Designer创建信号与槽的详细方法与实例
2020/03/08 Python
在tensorflow以及keras安装目录查询操作(windows下)
2020/06/19 Python
python利用google翻译方法实例(翻译字幕文件)
2020/09/21 Python
Pyinstaller打包Scrapy项目的实现步骤
2020/09/22 Python
python 基于selenium实现鼠标拖拽功能
2020/12/24 Python
纯CSS实现的大小渐变、渐远效果
2014/04/15 HTML / CSS
多视角3D逼真HTML5水波动画
2016/03/03 HTML / CSS
国际旅客访问北美最大的汽车租赁提供商:Alamo Rent A Car
2018/06/13 全球购物
英国最大的在线床超市:Bed Star
2019/01/24 全球购物
Ajax请求总共有多少种Callback
2016/07/17 面试题
学习全国两会精神心得体会范文
2014/03/17 职场文书
审计专业自荐信范文
2014/04/21 职场文书
车辆工程专业求职信
2014/04/28 职场文书
差生评语大全
2014/05/04 职场文书
你喜欢篮球吗?Python实现篮球游戏
2021/06/11 Python
vue特效之翻牌动画
2022/04/20 Vue.js