欢迎光临散文网 会员登陆 & 注册

程序作品(7)——家庭监控系统

2023-07-09 16:16 作者:Jerrycjk  | 我要投稿

筹划

在我家的后院中,经常会有诸如鸟、兔子一类的小动物出没(据邻居说还会有狐狸)。但是这些小动物出现的时间一般非常短,往窗外看的时候正好看到它们的几率非常小,用相机记录下来更是非常困难。

因此,我打算制作一个家庭监控系统来监控后院中出现的小动物,这个监控系统应当周期性记录后院的画面,并且可以作为服务器将记录下的图片按照用户的需求发送到他的电脑上,在收集到一定数量的图片后还可以快速筛出可能含有小动物的图片。

1. 周期性拍摄图片并响应客户端的请求

1.1 周期性拍摄图片

想要长期监控后院中的情景,我就必须让一台能够拍摄图片的计算机一直在窗边保持开机并运行我写的拍摄和服务器程序。此外,为了控制这个项目的成本,我必须选用家中的闲置设备,而且这台设备的能耗不能太高。

这里我选用树莓派4b单片机。这台单片机搭载了基于Linux系统的Raspberry Pi OS,可以运行python程序,可以外接摄像头,并且它的能耗也相对较低。

在软件方面,控制计算机拍照时我选用了python的picamera库。这个库可以调用树莓派自带的摄像头来拍摄和存储照片,并且可以将摄像头的画面实时显示在屏幕上以供预览。定时拍照的程序非常容易实现,这里不过多赘述。

1.2 作为服务器响应客户机请求

虽然我之前写过了很多服务器有关的程序,但是这个项目对服务器的需求和以前的项目有些许不一样。主要有两个不一样的地方:

1.2.1 传输大文件

在刚刚接触网络通信的时候,我就曾尝试使用最基本的socket语句传输一个图片。但是每次都只能接收到这个图片开头的一个kb,后面的信息就在传输的过程中“丢失”了。后来在写坦克动荡的重制版的时候,我才知道了粘包问题,也知道了必须接受多次才能完整接受到发出的信息。但是对于这个项目,坦克动荡中的收发函数还需要做一些改动。

在坦克动荡重制版中,我只考虑了粘包问题中的一次不能完整接受一条信息的情况。但是实际上,当发送的文件足够大的时候,还有可能出现一个信息被切成多个小段发送的情况。在这种情况下,我们就需要使用循环来保证程序完整地发送了信息。具体步骤如下:

  1.  将要发送的信息存在一个二进制字符串里,并用socket的send函数发送

  2. send函数会返回一个值,这个值表示待发送的字符串实际发送出的长度。为了防止由于文件过大而没有完整发送文件,我们需要判断这个返回值是否等于字符串的长度,如果不等于,则需要接着发送没有发完的部分。

1.2.2 Linux系统下的多线程
由于一个服务器往往要同时服务多台客户机,而且一台客户机所造成的报错(如客户机突然断开连接等)不能影响到其它客户机,因此在服务器中使用多线程是非常重要的。

在Windows系统下,多线程支持往待运行的函数中传入各种参数,其中包括socket库用于表示客户机连接的参数。在这种情况下,我们可以直接在主程序中循环等待客户机连接,一旦接收到一个连接,就用多线程运行一个处理客户机连接的函数,并把客户机的连接信息传进去。

但是由于某些原因,Linux系统的多线程不能传入socket表示客户机连接的参数。这就导致上述方法不能在树莓派上使用。在询问了chatGPT进行了大量的信息搜集后,我采用了如下办法:

  1. python中有一个叫做queue的库,可以创建可被多个线程访问的队列

  2. 在主程序里创建一个空队列用于在线程之间传递信息,并定义如下函数:

    accept():用于接受客户机的连接并将连接信息存到队列中;

    handle_client():这个函数开始的时候不断检测队列中是否有元素,一旦检测到队列中有元素(即有客户机被连接),就将该客户机从队列中推出来由自己处理,并开一个新的线程将自己再运行一遍

  3. 在启动服务器程序的时候,先开两个线程分别运行accept和handle_client函数,然后在主程序中控制拍照。

这样一来我们不仅将服务器程序和拍照程序结合到了一个程序中,也完美解决了Linux系统多线程不支持传递连接信息参数的问题。

2. 筛查图片

在图片识别这方面,python有非常多的第三方库可以很快做到这一点,但是老是调用第三方库太没意思了,因此我自己写了一个非常简陋的筛查图片中的小动物的程序。这个程序的思路大致是这样的:

由于我的监控系统拍摄照片的间隔时间非常短(15秒一张),因此相邻两张图片的差别不会特别大。利用这个特点,我可以对比相邻两张图片,如果它们之间有一个区域差别非常大,那么就可以初步确定这个区域有东西出现。

当然,我的筛查程序还没有经过训练,一些重要的参数,如区域的大小、区域之间差别的大小等还需要调整。

除了识别的准确度以外,识别的速度也是一个非常重要的指标。在第一次对后院进行拍摄的时候,我将拍摄程序运行了两三天,就得到了超过一万两千张照片。如果筛查程序的效率不高,那么识别这一万多张照片所需要的时间将会非常多。

鉴于python底下的运行效率,我本来计划用C++写识别程序,但是我对C++的文件操作还不是很熟悉,不能够在一个程序中读取多个文件。因此被迫转用python。

但是在询问了chatGPT查询了大量资料之后,我了解到了numpy库。这个库可以利用C语言对python程序中的特定简单运算进行加速,而且经过尝试,效果非常好。

最终,我将拍到的前七千张照片输入筛查程序进行筛查,这个程序筛查出了17张有小动物的图片中的11张,准确率还有进步的空间。

一些展望&flag
很明显,这个项目的潜力是非常大的。筛查程序的精度可以提高是一方面,另一方面我可以将这个程序做成apk的格式放到安卓手机上运行,甚至上传到应用市场上,这样家中的闲置手机就可以被用作监控,发挥它们的作用。但是由于apk格式和安卓系统的限制,python中只有很少数库可以被打包成apk格式。因此想要登录安卓系统,我必须要学习非常多的新的库的使用方法,并且更深入地了解安卓系统。这是一个不小的挑战。

一些拍到的小动物

完结撒花!(bushi

注:

  1. 封面的图不是用树莓派拍的

  2. 我已经将这个项目的所有源代码上传到百度网盘,点击“阅读原文”即可下载。链接:https://pan.baidu.com/s/16I5r3pi7kNqTaM-vkkRzzQ?pwd=ejv1提取码:ejv1

  3. 这个项目拍到的前七千张照片已经被我做成延时视频上传到b站Jerrycjk账号下。感兴趣的读者可以去观看。


程序作品(7)——家庭监控系统的评论 (共 条)

分享到微博请遵守国家法律