百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

继程序员奶爸用树莓派自制AI婴儿监视器后,网友实现远程监控

itomcoil 2025-02-13 12:31 17 浏览

近日,国外一位刚刚荣升奶爸的技术博主 Fabio Manganiello 为了更好地照看孩子,利用树莓派与 Tensorflow 自制了一个智能婴儿监视系统。

该系统不仅能在孩子啼哭时自动发出通知,还能够分析哭声推断出孩子的需求。

Fabio 首先给这个“智能婴儿监视器”定义了一些需要的功能:

  • 基于低成本的树莓派(RaspberryPI)与 USB 麦克风
  • 该设备不是一个单纯的对讲机。当孩子开始/停止哭泣时,它可以检测到孩子的哭声并发出通知(理想情况下是通过手机),或者跟踪仪表板上的数据点,或者运行相应的任务。
  • 该设备能够在扬声器,智能手机,电脑等设备上传输音频。
  • 系统不受源和扬声器之间距离的影响,无需在整个房子里将扬声器移来移去。
  • 配备一个摄像头,可以利用摄像头对孩子实时监控,当他一开始哭,就可以抓拍到图片或婴儿床的短视频,以检查有什么不对劲。

根据以上需求,Fabio 选用 RaspberryPi Zero 与 PiCamera 组合自制了一个监控设备:

简要步骤是通过 SD 卡给树莓派装上 Linux 操作系统,运行 Tensorflow 模型,采集婴儿啼哭的音频样本。有了足够的音频样本后,就能生成数据集并训练模型,然后利用模型对婴儿的啼哭进行行为预测。最后在手机上通过 VLC 应用程序或利用 RPi Camera Viewer 应用程序就能观看视频。

树莓派如何与Python实现远程监控?

依赖库

树莓派(服务器端)

安装系统

关于树莓派的系统如何安装我就不做介绍了,网上很多,也很容易。下面直接给个链接,照着做就是了:

安装好官方的raspbian系统后,最好先更新一下(不是必须的):

sudo apt-get update
sudo apt-get upgrade

安装opencv

通常安装opencv有两种方式:使用apt-get直接从软件源获取编译好的opencv,或是自己从官网下载源码编译后安装。我个人比较喜欢后者,通常在自己的电脑上都会自己取编译想要用的版本。

但是在树莓派上编译着实比较麻烦,各种依赖库的问题,如果不想折腾的话建议还是使用前者的方法。

sudo apt-get install libopencv-dev
sudo apt-get install python-opencv

安装PIL

PIL(python image library)是十分好用的一个可用于python的图像处理库,后面要用到它进行图像的压缩。

sudo apt-get install python-imaging

其他

如果还碰到其他的库没有的情况,请自行使用pip安装。

客户端

我的客户端就是自己的笔记本,环境都是很早就配好的,因为经常用到opencv、numpy等库。考虑到有些人的电脑可能没有安装好,所以还是简要介绍一下。自己配开发环境是最基本的技能了。

numpy

太常用了,不过安装是不要用pip来,可能会报错,我通常是使用如下指令来安装:

sudo apt-get install python-numpy

PIL——指令同树莓派。

sudo apt-get install python-imaging

opencv

可以直接apt-get安装,不过不能指定版本;我个人喜欢用opencv3.0以上的,所以是从源码安装的。相关安装教程请问度娘,花些时间就能搞定。

其他

如果在后面运行程序时碰到了某些库没有,可以考虑用pip安装或是前面一样使用sudo apt-get install python-(库的名字)

如何在树莓派上使用usb摄像头

1.首先更新firmware

2.插上usb摄像头,输入ls /dev, 查看dev中是否存在一个video0这个设备,如果有了说明系统识别了,如果不认,重复第一步确保firmware最新,还不行就换摄像头吧。

3.安装mplayer,输入

sudo apt-get install mplayer 

4.输入命令播放摄像头视频

sudo mplayer  tv:// 

程序实现

使用python在本地读取摄像头并实时显示

在进入正题之前,我们要先实现在本地读取摄像头,测试正常通过后再放到服务器上测试。
创建一个python脚本,名字为:local_camera.py,代码如下:

#coding=utf-8
import cv2

# 打开摄像头
capture = cv2.VideoCapture(0)

while True:
    # 从摄像头读取一帧图像;如果读取失败,ret为False,如果成功,ret为true;frame存储了那一帧的数据。
    ret, frame = capture.read()
    # print(ret)
    # 显示图像
    cv2.imshow("camera", frame)
    if cv2.waitKey(10) == 27:
        break

cv2.destroyAllWindows()
capture.release()

程序很简单,不多说了,运行通过后,再往下一步走。

数据源端

创建一个python脚本,名字为:src_camera,py,代码如下:

import cv2
import time
import socket
import Image
import StringIO

# 获取摄像头
cap = cv2.VideoCapture(0)
# 调整采集图像大小为640*480
cap.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 640)
cap.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 480)

# 这里的HOST对应树莓派的IP地址(自己输入ifconfig查),端口号自己随便定一个即可,但注意后面的程序中要保持统一
HOST, PORT = '192.168.0.113', 9999
# 连接服务器
sock =socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))

while True:
    # 获取一帧图像
    ret, img = cap.read()
    # 如果ret为false,表示没有获取到图像,退出循环
    if ret is False:
        print("can not get this frame")
        continue    

    # 将opencv下的图像转换为PIL支持的格式
    pi = Image.fromarray(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))
    buf = StringIO.StringIO()# 缓存对象
    pi.save(buf, format='JPEG')# 将PIL下的图像压缩成jpeg格式,存入buf中
    jpeg = buf.getvalue()# 从buf中读出jpeg格式的图像
    buf.close()
    transfer = jpeg.replace('\n', '\-n')# 替换\n为\-n,因为后面传输时,终止的地方会加上\n,可以便于区分
    print len(transfer), transfer[-1]
    sock.sendall(transfer + "\n")# 通过socket传到服务器
    # time.sleep(0.2)

sock.close()

这部分代码实现的功能是:在树莓派端读取摄像头,使用socket包连接到服务器,并将从摄像头读取的数据发送到服务器上。
注释都在程序中。程序中我们使用socket包来将数据传到服务器,为了减少数据量,所以我们还需要对原始图像进行压缩。而压缩则是通过PIL将图像压缩成jpeg格式,而PIL支持的图像格式与opencv不同,所以在程序中还对其进行了转换。

服务器端

创建一个python脚本,名字为:server_camera,py,代码如下:

import socket
import time


sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.bind(("192.168.0.113", 9999))# 注意bind的这里,IP地址和端口号都要与前面的程序中一样
sock.listen(2)# 监听端口

# 等待数据源端连接
src, src_addr = sock.accept()
print "Source Connected by", src_addr

# 等待目标端连接
dst, dst_addr = sock.accept()
print "Destination Connected by", dst_addr

while True:
    msg = src.recv(1024 *1024)
    if not msg:
        break
    try:
        dst.sendall(msg)
    except Exception as ex:
        dst, dst_addr = sock.accept()
        print "Destination Connected Again by", dst_addr
    except KeyboardInterrupt:
        print "Interrupted"
        break

src.close()
dst.close()
sock.close()

目标端(客户端)

创建一个python脚本,名字为:dst_camera,py,代码如下:

import cv2
import socket
import time
import Image
import StringIO
import numpy as np

# 注意IP地址和端口号与前面的程序中的保持一致
HOST, PORT = "192.168.0.113", 9999
# 连接到服务器
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((HOST, PORT))
f = sock.makefile()

cv2.namedWindow("camera")

while True:
    # 从服务器读取数据,一行的结尾是'\n',注意我们前面已经将每一帧数据的'\n'替换成'\-n',而结尾就是'\n'
    msg = f.readline()
    if not msg:
        break
    print len(msg), msg[-2]
    # 将'\-n'换回来成'\n'
    jpeg = msg.replace("\-n", "\n")
    buf = StringIO.StringIO(jpeg[0:-1])# 缓存数据
    buf.seek(0)
    pi = Image.open(buf)# 使用PIL读取jpeg图像数据
    # img = np.zeros((640, 480, 3), np.uint8)
    img = cv2.cvtColor(np.asarray(pi), cv2.COLOR_RGB2BGR)# 从PIL的图像转成opencv支持的图像     
    buf.close()
    cv2.imshow("camera", img)# 实时显示
    if cv2.waitKey(10) == 27:
        break

sock.close()
cv2.destroyAllWindows()

目标端,也可以说是客户端,这是真正的我们可以看到实际输出的部分了。从服务器读出数据然后显示即可。

运行结果

接下来看下运行结果了。

  1. 先运行服务器端的程序,输入python server_camera.py
  2. 然后运行数据源端的程序,输入python src_camera.py
  3. 最后在自己的客户端上运行程序,输入python dst_camera.py

如果你想要控制帧率,可以在src_camera.py中更改time.sleep(0.2)这句代码的参数,来控制延时时间。

相关推荐

selenium(WEB自动化工具)

定义解释Selenium是一个用于Web应用程序测试的工具。Selenium测试直接运行在浏览器中,就像真正的用户在操作一样。支持的浏览器包括IE(7,8,9,10,11),MozillaF...

开发利器丨如何使用ELK设计微服务中的日志收集方案?

【摘要】微服务各个组件的相关实践会涉及到工具,本文将会介绍微服务日常开发的一些利器,这些工具帮助我们构建更加健壮的微服务系统,并帮助排查解决微服务系统中的问题与性能瓶颈等。我们将重点介绍微服务架构中...

高并发系统设计:应对每秒数万QPS的架构策略

当面试官问及"如何应对每秒几万QPS(QueriesPerSecond)"时,大概率是想知道你对高并发系统设计的理解有多少。本文将深入探讨从基础设施到应用层面的解决方案。01、理解...

2025 年每个 JavaScript 开发者都应该了解的功能

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发。1.Iteratorhelpers开发者...

JavaScript Array 对象

Array对象Array对象用于在变量中存储多个值:varcars=["Saab","Volvo","BMW"];第一个数组元素的索引值为0,第二个索引值为1,以此类推。更多有...

Gemini 2.5编程全球霸榜,谷歌重回AI王座,神秘模型曝光,奥特曼迎战

刚刚,Gemini2.5Pro编程登顶,6美元性价比碾压Claude3.7Sonnet。不仅如此,谷歌还暗藏着更强的编程模型Dragontail,这次是要彻底翻盘了。谷歌,彻底打了一场漂亮的翻...

动力节点最新JavaScript教程(高级篇),深入学习JavaScript

JavaScript是一种运行在浏览器中的解释型编程语言,它的解释器被称为JavaScript引擎,是浏览器的一部分,JavaScript广泛用于浏览器客户端编程,通常JavaScript脚本是通过嵌...

一文看懂Kiro,其 Spec工作流秒杀Cursor,可移植至Claude Code

当Cursor的“即兴编程”开始拖累项目质量,AWS新晋IDEKiro以Spec工作流打出“先规范后编码”的系统工程思维:需求-设计-任务三件套一次生成,文档与代码同步落地,复杂项目不...

「晚安·好梦」努力只能及格,拼命才能优秀

欢迎光临,浏览之前点击上面的音乐放松一下心情吧!喜欢的话给小编一个关注呀!Effortscanonlypass,anddesperatelycanbeexcellent.努力只能及格...

JavaScript 中 some 与 every 方法的区别是什么?

大家好,很高兴又见面了,我是姜茶的编程笔记,我们一起学习前端相关领域技术,共同进步,也欢迎大家关注、点赞、收藏、转发,您的支持是我不断创作的动力在JavaScript中,Array.protot...

10个高效的Python爬虫框架,你用过几个?

小型爬虫需求,requests库+bs4库就能解决;大型爬虫数据,尤其涉及异步抓取、内容管理及后续扩展等功能时,就需要用到爬虫框架了。下面介绍了10个爬虫框架,大家可以学习使用!1.Scrapysc...

12个高效的Python爬虫框架,你用过几个?

实现爬虫技术的编程环境有很多种,Java、Python、C++等都可以用来爬虫。但很多人选择Python来写爬虫,为什么呢?因为Python确实很适合做爬虫,丰富的第三方库十分强大,简单几行代码便可实...

pip3 install pyspider报错问题解决

运行如下命令报错:>>>pip3installpyspider观察上面的报错问题,需要安装pycurl。是到这个网址:http://www.lfd.uci.edu/~gohlke...

PySpider框架的使用

PysiderPysider是一个国人用Python编写的、带有强大的WebUI的网络爬虫系统,它支持多种数据库、任务监控、项目管理、结果查看、URL去重等强大的功能。安装pip3inst...

「机器学习」神经网络的激活函数、并通过python实现激活函数

神经网络的激活函数、并通过python实现whatis激活函数感知机的网络结构如下:左图中,偏置b没有被画出来,如果要表示出b,可以像右图那样做。用数学式来表示感知机:上面这个数学式子可以被改写:...