基于树莓派打造你的个人感知终端

文摘   科技   2024-05-04 20:09   中国香港  

    哈喽大家好,好久没有给大家带来好玩的东西了。这次给大家介绍下开发的小玩意,让大家联动手机与树莓派,来进行实时的监控。

    首先我们用的是一台树莓派4B,加装了一个摄像头,并安装了Raspberry Pi OS系统。这个系统大家一般购买的时候店家会发给你,自己按照教程烧录就好啦。

(购买的树莓派)

(进入到系统界面)

    然后最关键的是我们要安装Linux版本的opencv,这个步骤相对较难,我直接找了别人装好的镜像,安装到了树莓派里,其他的诸如miniconda等大家自行安装。然后进行以下测试,如果桌面正常采集出example1.png那么我们基本上可以完成剩下的步骤!

import cv2import numpy as npcap = cv2.VideoCapture(0)  # 注意:这个地方本文的图片里没有参数0,但是应该传入0f, frame = cap.read()  # 此刻拍照cv2.imwrite("example1.png", frame)  # 将拍摄内容保存为png图片cap.release()  # 关闭调用的摄像头print('采集完成')

    如果我们想对摄像头采集的内容进行感知,来判断是否存在场景变化(例如实现有行人经过进行抓拍),那么最简单的思路是,间隔一秒钟进行拍照,然后对比一秒钟前后的图像变化,计算哈希相似度,如果相似度低于0.8那么我们判断有人经过或者场景发生了改变~

def compare_image(self, file_image1, file_image2, size=(256, 256), part_size=(64, 64)):    '''    'file_image1'和'file_image2'是传入的文件路径     可以通过'Image.open(path)'创建'image1' 和 'image2' Image 对象.     'size' 重新将 image 对象的尺寸进行重置,默认大小为256 * 256 .     'part_size' 定义了分割图片的大小.默认大小为64*64 .     返回值是 'image1' 和 'image2'对比后的相似度,相似度越高,图片越接近,达到1.0说明图片完全相同。    '''
image1 = Image.open(file_image1) image2 = Image.open(file_image2)
img1 = image1.resize(size).convert("RGB") sub_image1 = self.split_image(img1, part_size)
img2 = image2.resize(size).convert("RGB") sub_image2 = self.split_image(img2, part_size)
sub_data = 0 for im1, im2 in zip(sub_image1, sub_image2): sub_data += self.calculate(im1, im2)
x = size[0] / part_size[0] y = size[1] / part_size[1]
pre = round((sub_data / (x * y)), 6) # print(str(pre * 100) + '%') print('Compare the image result is: ' + str(pre)) return pre

(写一下对比的代码)

    同时我们设置While循环,这个系统就可以一直运行啦。但是仅仅计算出来,没办法传送到移动设备,感觉这还是不够智能。我们就引入邮件的SMTP服务,让他自动进行戒备。我们这里使用的是网易163邮箱,相关授权请自行百度。

    构造一个发邮箱请求:

def sendEmail(content,title):    sender = 'XXX@163.com'# 我用的163邮箱    receivers = ['XXXX']  # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
message_content = MIMEText(content, 'plain', 'utf-8')# 内容, 格式, 编码 message = MIMEMultipart('related') message['Subject'] = '摄像头识别检测' message['From'] = "{}".format(sender) message['To'] = ",".join(receivers) # message['Subject'] = title
# 第三方 SMTP 服务 mail_host = "smtp.163.com" # SMTP服务器 mail_user = "" # 用户名 mail_pass = "" #你的smtp密钥
img = MIMEImage(open('example1.png', 'rb').read(), _subtype='octet-stream') img.add_header('Content-Disposition', 'attachment', filename='example1.png') message.attach(img) message.attach(message_content) try: smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 启用SSL发信, 端口一般是465 smtpObj.login(mail_user, mail_pass)# 登录验证 smtpObj.sendmail(sender, receivers, message.as_string())# 发送 print("mail has been send successfully.") except smtplib.SMTPException as e: print(e)

    测试效果:

(手机收到邮件)

    其他的 一些好玩的,例如在树莓派上进行图像的边缘检测:

import cv2import numpy as npimg1=cv2.imread('/home/pi/Desktop/example1.png')img2=cv2.imread('/home/pi/Desktop/example2.png')# 从文件中读取图像image = cv2.imread('/home/pi/Desktop/example2.png', cv2.IMREAD_COLOR)# 将图像转换为灰度图gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)# 使用Canny算法进行边缘检测edges = cv2.Canny(gray, threshold1=30, threshold2=100)# 保存边缘检测结果的图像cv2.imwrite('edges_image.jpg', edges)# 显示原始图像和边缘检测结果cv2.imshow('Original', image)cv2.imshow('Edges', edges)# 等待用户按下任意键,然后关闭窗口cv2.waitKey(0)cv2.destroyAllWindows()

     还可以部署yolos-tiny来进行目标检测与识别~返回手机的信息可以更多,甚至可以接入大模型接口来进行场景描述(参见:城市字幕,教你如何利用图像跨模态推理空间知识)。后期我们还集成了人脸的年龄、情绪、族裔以及性别检测算法,也会将在接下来的教程中公开。

    做科学实验,数据的获取是非常关键的步骤,计划未来开发城市感知微型基站,集成更加多源的传感器,获取声热音光等多源信息,部署在车辆上,采集一手的城市数据,欢迎大家继续关注。

(采购了一些小的传感器)

    下一期继续给大家推送微博数据相关的技术与方法,教大家如何构建自己的公共事件社交媒体数据集,以下是一些前期文档:

微博签到数据的获取思路与实战

城市微博签到数据分享&地址解码与纠偏教程

北京市含地理坐标的微博数据分享&数据获取方法与科学研究问题

超越微博,小红书数据采集数据、代码和思路

    最后是本文分享的全部代码:

# -*- coding: UTF-8 -*-__author__ = 'zy'__time__ = '2020/5/24 20:21'#coding:utf8import osfrom PIL import Image,ImageDraw,ImageFileimport numpyimport pytesseract#import cv2#import imagehashimport collectionsimport cv2,time
def compare_image_with_hash(image_file1,image_file2, max_dif=0): """ max_dif: 允许最大hash差值, 越小越精确,最小为0 推荐使用 cv2.img_hash.averageHash """ ImageFile.LOAD_TRUNCATED_IMAGES = True hash_1 = None hash_2 = None with open(image_file1, 'rb') as fp: hash_1 = cv2.img_hash.averageHash(Image.open(fp)) print(hash_1) with open(image_file2, 'rb') as fp: hash_2 = cv2.img_hash.averageHash(Image.open(fp)) print(hash_2) dif = hash_1 - hash_2 print(dif) if dif < 0: dif = -dif if dif <= max_dif: return True else: return False
class CompareImage(): def calculate(self, image1, image2): g = image1.histogram() s = image2.histogram() assert len(g) == len(s), "error" data = [] for index in range(0, len(g)): if g[index] != s[index]: data.append(1 - abs(g[index] - s[index]) / max(g[index], s[index])) else: data.append(1) return sum(data) / len(g)

def split_image(self, image, part_size): pw, ph = part_size w, h = image.size sub_image_list = [] assert w % pw == h % ph == 0, "error" for i in range(0, w, pw): for j in range(0, h, ph): sub_image = image.crop((i, j, i + pw, j + ph)).copy() sub_image_list.append(sub_image)
return sub_image_list

def compare_image(self, file_image1, file_image2, size=(256, 256), part_size=(64, 64)): ''' 'file_image1'和'file_image2'是传入的文件路径 可以通过'Image.open(path)'创建'image1' 和 'image2' Image 对象. 'size' 重新将 image 对象的尺寸进行重置,默认大小为256 * 256 . 'part_size' 定义了分割图片的大小.默认大小为64*64 . 返回值是 'image1' 和 'image2'对比后的相似度,相似度越高,图片越接近,达到1.0说明图片完全相同。 '''
image1 = Image.open(file_image1) image2 = Image.open(file_image2)
img1 = image1.resize(size).convert("RGB") sub_image1 = self.split_image(img1, part_size)
img2 = image2.resize(size).convert("RGB") sub_image2 = self.split_image(img2, part_size)
sub_data = 0 for im1, im2 in zip(sub_image1, sub_image2): sub_data += self.calculate(im1, im2)
x = size[0] / part_size[0] y = size[1] / part_size[1]
pre = round((sub_data / (x * y)), 6) # print(str(pre * 100) + '%') print('Compare the image result is: ' + str(pre)) return pre

import smtplib,timefrom email.mime.text import MIMETextfrom email.mime.image import MIMEImagefrom email.mime.multipart import MIMEMultipart
def sendEmail(content,title): sender = 'XXX@163.com'# 我用的163邮箱 receivers = ['XXXX'] # 接收邮件,可设置为你的QQ邮箱或者其他邮箱
message_content = MIMEText(content, 'plain', 'utf-8')# 内容, 格式, 编码 message = MIMEMultipart('related') message['Subject'] = '摄像头识别检测' message['From'] = "{}".format(sender) message['To'] = ",".join(receivers) # message['Subject'] = title
# 第三方 SMTP 服务 mail_host = "smtp.163.com" # SMTP服务器 mail_user = "" # 用户名 mail_pass = "" #你的smtp密钥
img = MIMEImage(open('example1.png', 'rb').read(), _subtype='octet-stream') img.add_header('Content-Disposition', 'attachment', filename='example1.png') message.attach(img) message.attach(message_content) try: smtpObj = smtplib.SMTP_SSL(mail_host, 465) # 启用SSL发信, 端口一般是465 smtpObj.login(mail_user, mail_pass)# 登录验证 smtpObj.sendmail(sender, receivers, message.as_string())# 发送 print("mail has been send successfully.") except smtplib.SMTPException as e: print(e)
if __name__=='__main__':
while True: cap = cv2.VideoCapture(0) # 注意:这个地方本文的图片里没有参数0,但是应该传入0 f, frame = cap.read() # 此刻拍照 cv2.imwrite("example1.png", frame) # 将拍摄内容保存为png图片 cap.release() # 关闭调用的摄像头 print('采集完成') time.sleep(1)
cap = cv2.VideoCapture(0) # 注意:这个地方本文的图片里没有参数0,但是应该传入0 f, frame = cap.read() # 此刻拍照 cv2.imwrite("example2.png", frame) # 将拍摄内容保存为png图片 cap.release() # 关闭调用的摄像头
compare_image = CompareImage() result=compare_image.compare_image("example1.png","example2.png") print(result) if result<0.8: sendEmail(str(result), '温度测试反馈结果')

城市感知计算
认识世界和改造世界,张岩博士和志愿者团队搭建的非盈利城市科学分享平台,欢迎加好友学术交流。
 最新文章