基于opencv的家居智能安防机器视觉系统

2023-11-10

基于opencv的家居智能安防机器视觉系统(关键词:Windows、树莓派、python、opencv)

1.写在前面的话

大学4年很快过去了,因为疫情原因我们从大四上学期结束之后直接跳到了大学的尾声:毕业设计、毕业答辩、毕业的环境。回顾整个大学生活中最难忘的就是在光电创新实验室从事机器视觉课题研究的那段时间,感谢学院各位老师对我的帮助。这套系统为我的毕业设计内容,自认为有诸多不足,但是还是斗胆发布出来让各位从事视觉方面的同学查看。

2.opencv3和opencv4的区别

在我毕业设计项目进行的时候我选择了当时现行的opencv3版本,但是到了编写这篇文章的时候opencv发布了4.0版本。3和4版本基本一样,只是会有一点点的区别,注意即可。本篇文章将会从opencv4出发,使用opencv3版本的同学要注意一下,在获取轮廓的时候findContours函数返回结果由3.x的三个参数变为两个参数,不过我在后面也会标出不同的地方。

3.系统的整体结构设计

本文所开发的基于机器视觉的家居智能安防系统结构如图 1 所示。该系统采
用红外夜视摄像头作为采集家庭信息的传感器,在有异常现象的情况时会自动报
警,系统会通过 SMTP 协议将会采集当前视频帧发送到用户指定邮箱,同时发出
警报声,让业主及时查看即时报警画面采取行动。系统由树莓派、红外夜视摄像
头、物联网模块和电源模块组成。 树莓派上部署嵌入式 Linux 对采集到的图像进
行机器视觉处理、并利用树莓派上搭载的网卡模块进行联网通信;再把信息通过
SMTP 协议发往用户邮箱。 用户可以通过手机电脑等平台来查看采集到的图像信
息从而采取行动。

4.主要工作

1.硬件平台:包括摄像头(配套的图像采集卡或者集成)、镜头、嵌入式处理器
(树莓派或者其他平台)以及其他配件;
2.在嵌入式 Linux 系统上构建 python 以及 opencv 机器视觉环境;
3.建立视觉注意与运动视觉的关键算法,包括运动检测、实现动作捕捉、抓拍并
存储照片,同时可以在夜间使用;
4.当有运动物体进入超过一定阈值时可以实现自动报警,启动蜂鸣器;并将报警
通知通过邮件发送到邮箱;

5.代码部分

#-*-coding:utf-8-*-
# 导入必要的软件包
import argparse
import datetime
import imutils
import time
import cv2

import threading
import yagmail

# 创建参数解析器并解析参数
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video", help="path to the video file")
ap.add_argument("-a", "--min-area", type=int, default=500, help="minimum area size")
args = vars(ap.parse_args())
shot_idx = 0
# 如果video参数为None,那么我们从摄像头读取数据
if args.get("video", None) is None:
    camera = cv2.VideoCapture(0)#直接打开摄像头0获取图像

# 否则我们读取一个视频文件
else:
    camera = cv2.VideoCapture(args["video"])




def shijue() :
    shot_idx = 0
    # 遍历视频的每一帧
    # 初始化视频流的第一帧
    firstFrame = None
    while True:

        # 读入摄像头的帧
        (grabbed, frame) = camera.read()
        text = "Stop"
        flat = 0
        # 如果不能抓取到一帧,说明我们到了视频的结尾
        if not grabbed:
            break
        cv2.imshow('frame',frame)
        # 调整该帧的大小,转换为灰阶图像并且对其进行高斯模糊
        frame = imutils.resize(frame, width=500)
        # 对帧进行预处理,先转灰度图,再进行高斯滤波。
        # 用高斯滤波进行模糊处理,进行处理的原因:每个输入的视频都会因自然震动、光照变化或者摄像头本身等原因而产生噪声。对噪声进行平滑是为了避免在运动和跟踪时将其检测出来。
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        gray = cv2.GaussianBlur(gray, (21, 21), 0)
        cv2.imshow('gray', gray)
        # 如果第一帧是None,对其进行初始化

        if firstFrame is None:
            firstFrame = gray#一开始检测的话首帧会不存在,那么就把灰度图作为首帧
            continue
        # 计算当前帧和第一帧的不同
        # 对于每个从背景之后读取的帧都会计算其与北京之间的差异,并得到一个差分图(different map)。
        # 还需要应用阈值来得到一幅黑白图像,并通过下面代码来膨胀(dilate)图像,从而对孔(hole)和缺陷(imperfection)进行归一化处理
        frameDelta = cv2.absdiff(firstFrame, gray)
        thresh = cv2.threshold(frameDelta, 25, 255, cv2.THRESH_BINARY)[1]
        firstFrame = gray

        # 扩展阀值图像填充孔洞,然后找到阀值图像上的轮廓
        thresh = cv2.dilate(thresh, None, iterations=2)
        # 搜索轮廓
        contours, hierarchy = cv2.findContours(thresh, cv2.RETR_EXTERNAL,
                                                      cv2.CHAIN_APPROX_SIMPLE)
        #这里用的是opencv4,cv2.findContours返回了2个参数,但是用opencv3的话会返回3给参数,你要确保有足够的变量承接返回值可改成 binary, contours, hierarchy = cv.findContours(thresh, cv2.RETR_EXTERNAL,cv2.CHAIN_APPROX_SIMPLE)
        #返回值:contours:一个列表,每一项都是一个轮廓, 不会存储轮廓所有的点,只存储能描述轮廓的点hierarchy:一个ndarray, 元素数量和轮廓数量一样, 每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数

        """
            cv.findContours()
                参数:
                    1 要寻找轮廓的图像 只能传入二值图像,不是灰度图像
                    2 轮廓的检索模式,有四种:
                        cv2.RETR_EXTERNAL表示只检测外轮廓
                        cv2.RETR_LIST检测的轮廓不建立等级关系
                        cv2.RETR_CCOMP建立两个等级的轮廓,上面的一层为外边界,
                            里面的一层为内孔的边界信息。
                            如果内孔内还有一个连通物体,这个物体的边界也在顶层
                        cv2.RETR_TREE建立一个等级树结构的轮廓
                    3 轮廓的近似办法
                        cv2.CHAIN_APPROX_NONE存储所有的轮廓点,
                            相邻的两个点的像素位置差不超过1,
                            即max(abs(x1-x2),abs(y2-y1))==1
                        cv2.CHAIN_APPROX_SIMPLE压缩水平方向,垂直方向,对角线方向的元素,
                            只保留该方向的终点坐标,例如一个矩形轮廓只需4个点来保存轮廓信息
                返回值:
                    contours:一个列表,每一项都是一个轮廓, 不会存储轮廓所有的点,只存储能描述轮廓的点
                    hierarchy:一个ndarray, 元素数量和轮廓数量一样, 
                        每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],
                        分别表示后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号,如果没有对应项,则该值为负数
            """
        # 遍历轮廓
        for c in contours:
            # 轮廓太小忽略 有可能是斑点噪声

            if cv2.contourArea(c) < 5000:  # 该为args["min_area"]
                continue
            # 将轮廓画出来
            # compute the bounding box for the contour, draw it on the frame,
            # and update the text
            # 计算轮廓的边界框,在当前帧中画出该框
            flat = 1  # 设置一个标签,当有运动的时候为1
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 2)
            text = "Moving"
            # 在画面上显示运动

        # draw the text and timestamp on the frame
        # 在当前帧上写文字以及时间戳
        cv2.putText(frame, "Movement State: {}".format(text), (10, 20),
                    cv2.FONT_HERSHEY_SIMPLEX, 0.5, (0, 0, 255), 2)
        cv2.putText(frame, datetime.datetime.now().strftime("%A %d %B %Y %I:%M:%S%p"),
                    (10, frame.shape[0] - 10), cv2.FONT_HERSHEY_SIMPLEX, 0.35, (0, 0, 255), 1)

        # 显示当前帧并记录用户是否按下按键

        cv2.imshow("Thresh", thresh)
        cv2.imshow("Frame Delta", frameDelta)
        cv2.imshow("Security Feed", frame)
        #cv2.imwrite("/home/pi/Desktop/movement_detection/image.jpg", frame)#保存到某个位置,这里是树莓派


        if cv2.waitKey(1) & 0xFF == ord('q'):  # 按q保存一张图片
            # cv2.imwrite("E:\cpy\pictures\\pic.jpg", frame1)
            break

    camera.release()
    cv2.destroyAllWindows()


def qqyouxian(num):#这里是控制邮箱发送的函数
    yag = yagmail.SMTP(user="*****@qq.com", password="****你的密码", host="smtp.exmail.qq.com")#这里应该填入你需要用的邮箱,user=邮箱地址,password=邮箱的密码,host=邮箱的服务器域名,这里是qq企业邮
    contents = ["检测到运动问物体", "/home/pi/Desktop/movement_detection/image.jpg"]#正文部分 随意,后面的是在树莓派系统下的抓拍地址,自己可以改一下
    yag.send("usg1024@qq.com", "检测到运动问物体", contents)#目标邮箱
    yag.close()
    
    time.sleep(50)


def main():#设计了多线程并行,邮件发送和机器视觉部分不冲突
    """创建启动线程"""
    t_sing = threading.Thread(target=shijue)
    t_dance = threading.Thread(target=qqyouxian, args=(6, ))
    t_sing.start()
    t_dance.start()


if __name__ == '__main__':
    main()

6.演示效果

视频演示:

https://www.bilibili.com/video/BV1e541147dR/

正经:基于树莓派的家庭安防系统(机器视觉)


移动端演示:


7.总结

时间过得飞快,转眼就到了毕业的时候了,希望这篇文章可以帮到你。

 
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

基于opencv的家居智能安防机器视觉系统 的相关文章

随机推荐

  • Win10环境python3.7安装dlib模块

    自己按照别人的博客安装了一下dlib 测试成功 在这里自己也稍微总结一下 博客原文 https blog csdn net zhang475546259 article details 84104368 1 安装VS201x 全称visua
  • 简单支付验证-SPV

    SPV的来源 在比特币整个生态圈里 大部分都是普通用户 即只有基本的比特币投资及消费支付需要的用户 他们可能没有矿机 没有高端配置的电脑 那么他们是否也要运行一个全节点程序呢 要知道 现在官方显示的结果 比特币所有区块数据目前在120G左右
  • webstorm等JetBrains全家桶搜索任何插件都无反应

    使用webstorm搜索任何插件都无反应 打开webstorm设置 搜索settings或者是System Settings 找到HTTP Proxy 设置AUTO detect proxy settings后 点击右下角的Apply应用后
  • vue 中provide的用法_Vue中使用provide和inject

    相信大家在工作中一定遇到过多层嵌套组件 而vue 的组件数据通信方式又有很多种 比如vuex dollar parent与 dollar children prop dollar emit与 dollar on dollar attrs与
  • 为什么需要对数值类型的特征做归一化?

    为什么需要对数值类型的特征做归一化 1 举例子 比如分析一个人的身高和体重对健康的影响 身高的单位是m 范围是1 6 1 8 体重的单位是kg 在50kg 100kg之间 分析出的结果自然会倾向于数值差异较大的体重特征 因此我们需要数值归一
  • 新版Spring Boot(10)- Spring Boot 整合数据持久层(1)

    1 整合JdbcTemplate Service Description TODO Author tzb Date 2021 8 22 10 23 Version 1 0 Service public class UserService A
  • 【Mysql】删除表记录,并限制条数

    删除表数据 好删 那如果要限制条数 如何删除呢 例如 有个表tag list 我要删除aid为6666的前100条数据 sql如下 删除表记录limit限制条数 delete from tag list where aid 6666 lim
  • JUC 六. 线程中断 与 LockSupport

    目录 一 基础理解 如何退出一个线程 volatile 与 AtomicBoolean 中断线程示例 Thread中自带的中断api示例 阻塞状态线程中断时异常解决 二 Thread中自带的中断底层分析 三 总结 一 基础理解 先了解几个问
  • 打印九九口诀表(pta练习题)

    下面是一个完整的下三角九九口诀表 本题要求对任意给定的一位正整数N 输出从1 1到N N的部分口诀表 输入格式 输入在一行中给出一个正整数N 1 N 9 输出格式 输出下三角N N部分口诀表 其中等号右边数字占4位 左对齐 include
  • AIDL原理和相关文件解析

    Binder概述 相信从事Android相关的研发人员 都对Binder有个或多或少的了解 相关技术博客也有一大推 我今天对Binder的学习过程进行一个记录 理论性的叙述会少一点 更多的是基于AS自动生成的AIDL文件进行代码分析 但读者
  • 【Java基础】使用Java 8的Stream API来简化Map集合的操作

    在 Java 8 中引入的 Stream API 是一种非常强大的函数式编程工具 可以帮助开发者更加方便地对集合进行操作和处理 而在 Map 集合中 Stream API 的使用也能够极大地简化代码 并提升程序效率和可读性 在本文中 我们将
  • 网络基础通过子网掩码 计算主机数网络范围

    192 168 11 16 27 主机的个数为32 27 5 2 5 32 32 2 30主机数为30 主机范围是0 31 63 95 必须是32的倍数 16在0 32之间 31是广播地址 网络号是192 168 11 0
  • 白话学习防火墙3 之防火墙工作模式(适用于IPS、IDS、WAF等其他安全设备)

    说白了 透明模式就是当交换机使 路由模式就是当路由使 混杂就是杂交物种 即当作路由使 又当作交换机使 透明模式 透明模式一般用于网络建设完 网络功能基本已经实现的情况下 用户需要加装防火墙以实现安全区域隔离的要求 早期也称之为桥模式 桥这个
  • jvm的内存模型之eden区

    浅谈java内存模型 不同的平台 内存模型是不一样的 但是jvm的内存模型规范是统一的 其实java的多线程并发问题最终都会反映在java的内存模型上 所谓线程安全无 非是要控制多个线程对某个资源的有序访问或修改 总结java的内存模型 要
  • 如何完成卷积神经网络有关的毕业设计

    前言 毕业设计对于每个学生而言都是一种十分痛苦的渡劫仪式 尤其是当你拿到的是完全陌生的毕业设计的时候 内心无疑有各种王尼玛从心中飘过 我在这里聊聊我在完成毕设的过程中得到的一些经验教训 因为我的毕业设计主题是卷积神经网络 所以在这里我的话题
  • 【云计算与数据中心规划】【期末复习题】【2022秋】

    文章目录 一 单选题 共7题 二 多选题 共15题 三 填空题 共7题 四 判断题 共5题 五 简答题 共7题 Reference 题量 41 满分 100 0 一 单选题 共7题 1 以下哪个虚拟机系统可以独立安装在计算机硬件之上 不需要
  • 什么是整洁的代码

    点击蓝色 五分钟学算法 关注我哟 加个 星标 天天中午 12 15 一起学算法 作者 xybaby 来源 https www cnblogs com xybaby p 11335829 html 写出整洁的代码 是每个程序员的追求 clea
  • opengl es3.0学习篇八:纹理

    OpenGL ESMIP 开发十年 就只剩下这套架构体系了 gt gt gt 学习内容来源and参考 opengl es 3 0编程指南 https www jianshu com p 4d8d35288a0f 3D图形渲染最基本的操作之一
  • 05 神经网络语言模型(独热编码+词向量的起源)

    博客配套视频链接 https space bilibili com 383551518 spm id from 333 1007 0 0 b 站直接看 配套 github 链接 https github com nickchen121 Pr
  • 基于opencv的家居智能安防机器视觉系统

    基于opencv的家居智能安防机器视觉系统 关键词 Windows 树莓派 python opencv 1 写在前面的话 大学4年很快过去了 因为疫情原因我们从大四上学期结束之后直接跳到了大学的尾声 毕业设计 毕业答辩 毕业的环境 回顾整个