zoukankan      html  css  js  c++  java
  • 2020系统综合实践 期末大作业 27组

    一.项目介绍

    1.概述

    本项目是将树莓派摄像头采集到的视频流发送至实时监控网站,如果出现人像则通过人脸识别确定,并截取该图像发送至收信邮箱。

    2.思路与分工

    本次实验,我们大体划分成三个模块。

    • 第一:人脸识别模块。采用opencv的cv2.CascadeClassifier级联分类器进行人脸识别捕捉。由翁正凯完成。
    • 第二:搭建实时视频流网站将采集到的实时视频发送到我们建立的网页,这一步我们采用flask框架搭建。由张启荣完成。
    • 第三:发送采集到的人脸关键帧图片至我们指定的qq邮箱,这--步我们是采用smtp来进行的。由李家涌完成。

    二.项目实现

    1.安装opencv

    实验七已经安装过opencv环境,所以不再赘述,直接沿用上次的环境。

    2.安装项目依赖

    requestment.txt

    imutils
    flask
    picamera[array]
    Flask-BasicAuth==0.2.0
    
    pip install -r requirements.txt
    

    3.人脸识别模块

    camera.py

    import cv2
    from imutils.video.pivideostream import PiVideoStream   #处理视频流的库
    import imutils  #图像处理工具包,也可用于视频的处理,如摄像头、本地文件等
    import time
    import numpy as np  #运行速度非常快的数学库,主要用于数组计算
    
    class VideoCamera(object):
        def __init__(self, flip = False):   #类初始化,self指向类实例对象本身
            self.vs = PiVideoStream().start()   #启动线程视频流
            self.flip = flip
            time.sleep(2.0)
    
        def __del__(self):  #对象销毁时调用,用于释放资源
            self.vs.stop()  #停止线程并释放所有资源
    
        def flip_if_needed(self, frame):    #翻转当前这帧的图片, frame:帧
            if self.flip:
                return np.flip(frame, 0)    #np.flip用于翻转数组,NumPy的np.flip()函数允许沿着某一个轴翻转数组的内容。当使										用np.flip时,指定要反转的数组和轴。如果不指定轴将沿着输入数组的所有轴反转内容。
            return frame                    #np.flip(frame,0),0:按行翻转,1:按列翻转,不指定:按行按列翻转
    
        def get_frame(self):   				 #得到当前帧
            frame = self.flip_if_needed(self.vs.read()) #self.vs.read()返回当前帧
            ret, jpeg = cv2.imencode('.jpg', frame)     #cv2.imencode()函数是将图片格式转换(编码)成流数据,赋值到内存缓													存中;主要用于图像数据格式的压缩,方便网络传输。
            return jpeg.tobytes()                       #image.tobytes()函数,以字节对象的形式返回图像
    
        def get_object(self, classifier):               #调用分类器识别人脸,返回识别到的人脸图片
            found_objects = False
            frame = self.flip_if_needed(self.vs.read()).copy()      #复制视频流采集到的帧,用于进行人脸判断
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)          #将读取到的帧进行颜色空间转换,有些图像可能在 RGB 颜																	色空间信息不如转换到其它颜色空间更清晰
    
            objects = classifier.detectMultiScale(      #调整函数的参数使检测结果更加精确
                gray,
                scaleFactor=1.1,
                minNeighbors=5,
                minSize=(30, 30),
                flags=cv2.CASCADE_SCALE_IMAGE
            )
    
            if len(objects) > 0:                        #如果有识别到人脸
                found_objects = True
    
            # Draw a rectangle around the objects       #在人脸周围画一个矩形框
            for (x, y, w, h) in objects:
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
    
            ret, jpeg = cv2.imencode('.jpg', frame)
            return (jpeg.tobytes(), found_objects)      #如果识别到人脸,就将其图片转换成流数据并返回
    
    
    

    4,建立实时监控网站并发送实时视频流

    main.py

    import cv2
    import sys 
    from mail import sendEmail #从mail.py导入
    from flask import Flask, render_template, Response
    from camera import VideoCamera #从camera.py导入
    from flask_basicauth import BasicAuth #
    import time
    import threading
    
    email_update_interval = 5 # 发送邮件时间间隔 秒为单位
    video_camera = VideoCamera(flip=True) # 创建一个camera对象
    object_classifier = cv2.CascadeClassifier("models/facial_recognition_model.xml"  # 级联分类器 具体模型是网上找的开源已经训练好的
    
    # https://flask-basicauth.readthedocs.io/en/latest/ 用于简单安全认证
    app = Flask(__name__)
    app.config['BASIC_AUTH_USERNAME'] = 'pi'
    app.config['BASIC_AUTH_PASSWORD'] = 'pi'
    app.config['BASIC_AUTH_FORCE'] = True
    
    basic_auth = BasicAuth(app) 
    last_epoch = 0
    
    def check_for_objects():#确定当前有识别到人脸并且已经过了上次发送间隔
    	global last_epoch
    	while True:
    		try:
    			frame, found_obj = video_camera.get_object(object_classifier) #得到人脸识别的关键帧
    			if found_obj and (time.time() - last_epoch) > email_update_interval:
    				last_epoch = time.time()
    				print ("Sending email...")
    				sendEmail(frame)
    				print ("done!") #成功
    		except:
    			print ("Error sending email: "), sys.exc_info()[0] #抛出异常
    
    @app.route('/')
    @basic_auth.required
    def index():
        return render_template('index.html') #模板渲染
    
    #https://www.jianshu.com/p/a262b3c42386
    def gen(camera):#使用生成器产生实时数据 用于实时看到监控
        while True:
            frame = camera.get_frame()
            yield (b'--frame
    '
                   b'Content-Type: image/jpeg
    
    ' + frame + b'
    
    ')#每一帧包含的信息
    
    @app.route('/video_feed')
    def video_feed(): #发送视频流至搭建的网站 在index.html进行响应
        return Response(gen(video_camera),
                        mimetype='multipart/x-mixed-replace; boundary=frame') #实现视频流的基本格式
    
    if __name__ == '__main__': #创建线程
        t = threading.Thread(target=check_for_objects, args=())
        t.daemon = True #线程守护
        t.start()
        app.run(host='0.0.0.0', debug=False)
    

    5.使用smtp发送图片至目标邮箱

    注意:若要使用QQ邮箱的SMTP服务,需要到QQ邮箱开启相关服务。

    mail.py

    import smtplib
    from email.mime.multipart import MIMEMultipart
    from email.mime.text import MIMEText
    from email.mime.image import MIMEImage
    from PIL import Image
    
    # 邮件发送方(QQ邮箱)
    fromEmail = '1512386791@qq.com'
    # 发送方QQ邮箱授权码
    fromEmailPassword = 'hpftfrejtseff***'
    
    # 收件方
    toEmail = '1730166565@qq.com'
    
    def sendEmail(image):
        # 多个MIME对象的集合
        msgRoot = MIMEMultipart()
        # 主题
        msgRoot['Subject'] = 'Security Update'
        # 收件人邮箱
        msgRoot['From'] = fromEmail
        # 发件人邮箱
        msgRoot['To'] = toEmail
        msgRoot.preamble = 'Raspberry pi security camera update'
    
        msgAlternative = MIMEMultipart('alternative')
        msgRoot.attach(msgAlternative)
        msgText = MIMEText('Smart security cam found object')
        msgAlternative.attach(msgText)
    
        msgText = MIMEText('<img src="cid:image1">', 'html')
        msgAlternative.attach(msgText)
    
        # 添加捕获的图片
        msgImage = MIMEImage(image)
        msgImage.add_header('Content-ID', '<image1>')
        msgRoot.attach(msgImage)
    
        # 连接SMTP服务器
        smtp = smtplib.SMTP('smtp.qq.com', 587)
        smtp.starttls()
        # 登录邮箱
        smtp.login(fromEmail, fromEmailPassword)
        # 发送邮件
        smtp.sendmail(fromEmail, toEmail, msgRoot.as_string())
        # 退出,断开连接
        smtp.quit()
    
    

    6.本地初步运行

    python3 main.py

    注:终端提示”Sending email“即表明摄像头识别到人脸,“done”表发送邮件至指定收件箱完成。

    7.布置内网穿透

    采用Sunny-Ngrok实现内网穿透。使得通过外部网络可以访问实时视频流监控网站,而不局限于同一局域网

    (1)首先到Sunny-Ngrok官网注册一个账号并开通隧道

    (2)下载客户端

    这里选择的版本是Linux ARM版本

    (3)解压至树莓派

    (4)运行

    ./sunny clientid 2f39592879c6728f

    注:后面跟着的这串字符就是注册得到的隧道ID,先运行上面这句,然后再运行main.py,此时就可以在外部网络通过访问http://daydream.free.idcfengye.com 来查看监控视频.

    查看到的监控视频

    三.项目部署至docker

    1.项目结构

    2.自定义镜像

    (1)dockerfile

    FROM opencv1
    RUN mkdir /myapp
    WORKDIR /myapp
    COPY myapp .
    

    (2)构建镜像

    docker build -t opencv3 .

    (3)创建并运行容器

    docker run -it --device=/dev/vchiq --device=/dev/video0 --name security opencv3 
    

    安装依赖

    pip install -r requestments.txt
    

    (4)保存镜像

    (5)运行

    进入上面创建好的容器内,运行main.py

    pythn3 main.py

    四.总结

    (1)组员总结

    翁正凯:本次实验我负责的是摄像头模块的人脸识别部分,一开始我并不知道怎么对摄像头采集到视频进行处理,如何截取每一帧图片进行逐帧分析并识别该帧中是否存在人脸,以及要用到哪些包之类的。但是没办法,也只能硬着头皮去做,在网上查了很多资料后,才知道要处理视频流要用到 imutils 下的 pivideostream 这个包,于是在GitHub上找到了imutils的源码库,进行阅读,并试着慢慢写出代码。遇到的最大一个问题还是对python的不熟悉,语法上的不熟悉使我吃了蛮大的亏,比如定义python类时,为什么一定要定义init()方法等等。不过leaning by doning,在写代码的过程中,学习到了很多新知识。总的来说,本次实验着实令我开阔了眼界,知道了原来树莓派还可以这么玩,从某种程度上来讲,我们这次的项目也让我见识到了什么叫“万物互联”。

    张启荣:总的来说这次实验的代码量并不大,但是我们自认为是一个流程较为完善的小而精致的项目,未来还具有拓展性,通过本次实验我学习到了对于一个人脸识别项目的完整流程,我们除了没有自己训练人脸数据,其余都是我们自己写,我所负责的部分是网站搭建和视频流传输,这让我对flask也有了更深一些了解,因为事情太多了,后续如果有时间,我们可能会对应用进行拓展,然后对应用进行精修,比如对网站优化美化,降低延迟,提高精度等。总的来说这个项目让我受益匪浅。

    李家涌:这次实验我主要负责的是发送邮件和内网穿透的实现,实验过程中了解到了SMTP,以及python中smtp的客户端实现的模块smtplib,实现邮件消息处理的模块email,学会了使用python来发送邮件。内网穿透方面由于没有公网ip和vps采用的是现成服务器,没能自己实现还是比较遗憾的。总的来说还是收获满满。

    (2)组内贡献比

    小组成员 中期分工 本次分工 贡献比
    翁正凯 树莓派操作,人脸识别模块 树莓派操作、微服务部署 33.3%
    张启荣 视频流网站搭建 微服务部署 33.3%
    李家涌 基于SMTP的邮件发送模块 实现内网穿透 33.3%
  • 相关阅读:
    Liberty Mutual Property Inspection, Winner's Interview: Qingchen Wang
    均方根值(RMS)+ 均方根误差(RMSE)+标准差(Standard Deviation)
    Comparing Differently Trained Models
    Stochastic Optimization Techniques
    Here’s just a fraction of what you can do with linear algebra
    14种机器学习常见算法分类汇总
    高速充电技术介绍
    javacc学习总结
    组合查询(机房重构知识点总结)
    Linux下vi编辑器的使用
  • 原文地址:https://www.cnblogs.com/ZKweng/p/13199597.html
Copyright © 2011-2022 走看看