Python 物联网入门指南(五)(2)https://developer.aliyun.com/article/1507234
使用 Flask 框架控制设备
让我们尝试使用 Flask 框架在家中打开/关闭电器。在之前的章节中,我们使用PowerSwitch Tail II来控制树莓派 Zero 上的台灯。让我们尝试使用 Flask 框架来控制相同的东西。按照以下图示连接 PowerSwitch Tail:
使用 Flask 框架控制台灯
根据 Flask 框架文档,可以将 URL 路由到特定函数。例如,可以使用route()
将/lamp/
绑定到control()
函数:
@app.route("/lamp/<control>") def control(control): if control == "on": lights.on() elif control == "off": lights.off() return "Table lamp is now %s" % control
在前面的代码片段中,是一个可以作为参数传递给绑定函数的变量。这使我们能够打开/关闭灯。例如,
:5000/lamp/on
打开灯,反之亦然。把它们放在一起,我们有这样:
#!/usr/bin/python3 from flask import Flask from gpiozero import OutputDevice app = Flask(__name__) lights = OutputDevice(2) @app.route("/lamp/<control>") def control(control): if control == "on": lights.on() elif control == "off": lights.off() return "Table lamp is now %s" % control if __name__ == "__main__": app.run('0.0.0.0')
上述示例可与本章一起下载,文件名为appliance_control.py
。启动基于 Flask 的 Web 服务器,并在另一台计算机上打开 Web 服务器。为了打开灯,输入<树莓派 Zero 的 IP 地址>:5000/lamp/on
作为 URL:
这应该打开灯:
因此,我们建立了一个简单的框架,可以控制网络中的电器。可以在 HTML 页面中包含按钮,并将它们路由到特定的 URL 以执行特定的功能。Python 中还有几个其他框架可以开发 Web 应用程序。我们只是向您介绍了 Python 可能的不同应用程序。我们建议您查看本书的网站,了解更多示例,例如使用 Flask 框架控制万圣节装饰和其他节日装饰。
摘要
在本章中,我们讨论了 Python 中的try
/except
关键字。我们还讨论了从互联网检索信息的应用程序,以及将传感器事件发布到互联网。我们还讨论了 Python 的 Flask Web 框架,并演示了在网络中控制电器。在下一章中,我们将讨论 Python 中的一些高级主题。
第十六章:使用 Python 可以开发的一些很棒的东西
在本章中,我们将讨论 Python 中的一些高级主题。我们还将讨论一些独特的主题(如图像处理),让您开始使用 Python 进行应用程序开发。
使用 Raspberry Pi Zero 进行图像处理
Raspberry Pi Zero 是一款价格便宜的硬件,配备了 1 GHz 处理器。虽然它不足以运行某些高级图像处理操作,但可以帮助您在 25 美元的预算内学习基础知识(Raspberry Pi Zero 和摄像头的成本)。
我们建议您在 Raspberry Pi Zero 上使用 16 GB(或更高)的卡来安装本节讨论的图像处理工具集。
例如,您可以使用 Raspberry Pi Zero 来跟踪后院的鸟。在本章中,我们将讨论在 Raspberry Pi Zero 上开始图像处理的不同方法。
为了在本节中使用摄像头测试一些示例,需要 Raspberry Pi Zero v1.3 或更高版本。检查您的 Raspberry Pi Zero 的背面以验证板的版本:
识别您的 Raspberry Pi Zero 的版本
OpenCV
OpenCV是一个开源工具箱,包括为图像处理开发的不同软件工具。OpenCV 是一个跨平台的工具箱,支持不同的操作系统。由于 OpenCV 在开源许可下可用,全世界的研究人员通过开发工具和技术为其增长做出了贡献。这使得开发应用程序相对容易。OpenCV 的一些应用包括人脸识别和车牌识别。
由于其有限的处理能力,安装框架可能需要几个小时。在我们这里大约花了 10 个小时。
我们按照www.pyimagesearch.com/2015/10/26/how-to-install-opencv-3-on-raspbian-jessie/
上的指示在 Raspberry Pi Zero 上安装 OpenCV。我们特别按照了使用 Python 3.x 绑定安装 OpenCV 的指示,并验证了安装过程。我们大约花了 10 个小时来完成在 Raspberry Pi Zero 上安装 OpenCV。出于不重复造轮子的考虑,我们不会重复这些指示。
安装的验证
让我们确保 OpenCV 安装及其 Python 绑定工作正常。启动命令行终端,并确保您已经通过执行workon cv
命令启动了cv
虚拟环境(您可以验证您是否在cv
虚拟环境中):
验证您是否在 cv 虚拟环境中
现在,让我们确保我们的安装工作正常。从命令行启动 Python 解释器,并尝试导入cv2
模块:
>>> import cv2 >>> cv2.__version__ '3.0.0'
这证明了 OpenCV 已经安装在 Raspberry Pi Zero 上。让我们编写一个涉及 OpenCV 的hello world示例。在这个示例中,我们将打开一张图像(这可以是您的 Raspberry Pi Zero 桌面上的任何彩色图像),并在将其转换为灰度后显示它。我们将使用以下文档来编写我们的第一个示例:docs.opencv.org/3.0-beta/doc/py_tutorials/py_gui/py_image_display/py_image_display.html
。
根据文档,我们需要使用imread()
函数来读取图像文件的内容。我们还需要指定要读取图像的格式。在这种情况下,我们将以灰度格式读取图像。这由作为函数的第二个参数传递的cv2.IMREAD_GRAYSCALE
来指定:
import cv2 img = cv2.imread('/home/pi/screenshot.jpg',cv2.IMREAD_GRAYSCALE)
现在图像以灰度格式加载并保存到img
变量中,我们需要在新窗口中显示它。这是通过imshow()
函数实现的。根据文档,我们可以通过将窗口名称指定为第一个参数,将图像指定为第二个参数来显示图像:
cv2.imshow('image',img)
在这种情况下,我们将打开一个名为image
的窗口,并显示我们在上一步加载的img
的内容。我们将显示图像,直到收到按键。这是通过使用cv2.waitKey()
函数实现的。根据文档,waitkey()
函数监听键盘事件:
cv2.waitKey(0)
0
参数表示我们将无限期等待按键。根据文档,当以毫秒为单位的持续时间作为参数传递时,waitkey()
函数会监听指定持续时间的按键。当按下任何键时,窗口会被destroyAllWindows()
函数关闭:
cv2.destroyAllWindows()
将所有部件组装在一起,我们有:
import cv2 img = cv2.imread('/home/pi/screenshot.jpg',cv2.IMREAD_GRAYSCALE) cv2.imshow('image',img) cv2.waitKey(0) cv2.destroyAllWindows()
上述代码示例可在本章的opencv_test.py
中下载。安装 OpenCV 库后,尝试加载图像,如本示例所示。它应该以灰度加载图像,如下图所示:
树莓派桌面以灰度加载
这个窗口会在按下任意键时关闭。
向读者提出挑战
在上面的示例中,窗口在按下任意键时关闭。查看文档,确定是否可能在按下鼠标按钮时关闭所有窗口。
将相机安装到树莓派 Zero
测试我们下一个示例需要相机连接器和相机。购买相机和适配器的一个来源如下:
名称 | 来源 |
树莓派 Zero 相机适配器 | thepihut.com/products/raspberry-pi-zero-camera-adapter |
树莓派相机 | thepihut.com/products/raspberry-pi-camera-module |
执行以下步骤将相机安装到树莓派 Zero 上:
- 第一步是将相机连接到树莓派 Zero。相机适配器可以安装如下图所示。抬起连接器标签,滑动相机适配器并轻轻按下连接器:
- 我们需要在树莓派 Zero 上启用相机接口。在桌面上,转到首选项并启动树莓派配置。在树莓派配置的接口选项卡下,启用相机,并保存配置:
启用相机接口
- 通过从命令行终端运行以下命令来拍照测试相机:
raspistill -o /home/pi/Desktop/test.jpg
- 它应该拍照并保存到树莓派桌面上。验证相机是否正常工作。如果无法使相机工作,我们建议查看树莓派基金会发布的故障排除指南:
www.raspberrypi.org/documentation/raspbian/applications/camera.md
。
相机电缆有点笨重,拍照时可能会有些困难。我们建议使用相机支架。我们发现这个很有用(如下图所示)a.co/hQolR7O
:
使用树莓派相机的支架
让我们试试相机,并与 OpenCV 库一起使用:
- 我们将使用相机拍照,并使用 OpenCV 框架显示它。为了在 Python 中访问相机,我们需要
picamera
包。可以按照以下方式安装:
pip3 install picamera
- 让我们确保包能够按预期使用一个简单的程序。
picamera
包的文档可在picamera.readthedocs.io/en/release-1.12/api_camera.html
找到。 - 第一步是初始化
PiCamera
类。接下来是翻转图像,使其在垂直轴上翻转。这仅在相机倒置安装时才需要。在其他安装中可能不需要:
with PiCamera() as camera: camera.vflip = True
- 在拍照之前,我们可以使用
start_preview()
方法预览即将捕获的图片:
camera.start_preview()
- 在我们拍照之前,让我们预览
10
秒钟。我们可以使用capture()
方法拍照:
sleep(10) camera.capture("/home/pi/Desktop/desktop_shot.jpg") camera.stop_preview()
capture()
方法需要文件位置作为参数(如前面的代码片段所示)。完成后,我们可以使用stop_preview()
关闭相机预览。- 总结一下,我们有:
from picamera import PiCamera from time import sleep if __name__ == "__main__": with PiCamera() as camera: camera.vflip = True camera.start_preview() sleep(10) camera.capture("/home/pi/Desktop/desktop_shot.jpg") camera.stop_preview()
上述代码示例可与本章一起下载,文件名为picamera_test.py
。使用相机拍摄的快照如下图所示:
使用树莓派摄像头模块捕获的图像
- 让我们将此示例与上一个示例结合起来——将此图像转换为灰度并显示,直到按下键。确保您仍然在
cv
虚拟环境工作空间中。 - 让我们将捕获的图像转换为灰度,如下所示:
img = cv2.imread("/home/pi/Desktop/desktop_shot.jpg", cv2.IMREAD_GRAYSCALE)
以下是捕获后转换的图像:
图像在捕获时转换为灰度
- 现在我们可以按如下方式显示灰度图像:
cv2.imshow("image", img) cv2.waitKey(0) cv2.destroyAllWindows()
修改后的示例可作为picamera_opencvtest.py
进行下载。
到目前为止,我们已经展示了在 Python 中开发图像处理应用程序。我们还建议查看 OpenCV Python 绑定文档中提供的示例(在本节介绍部分提供了链接)。
语音识别
在本节中,我们将讨论在 Python 中开发语音识别示例涉及语音识别。我们将利用requests
模块(在上一章中讨论)来使用wit.ai
(wit.ai/
)转录音频。
有几种语音识别工具,包括 Google 的语音 API、IBM Watson、Microsoft Bing 的语音识别 API。我们以wit.ai
为例进行演示。
语音识别在我们希望使树莓派零对语音命令做出响应的应用中非常有用。
让我们回顾使用wit.ai
在 Python 中构建语音识别应用程序(其文档可在github.com/wit-ai/pywit
找到)。为了进行语音识别和识别语音命令,我们需要一个麦克风。但是,我们将演示使用一个现成的音频样本。我们将使用一篇研究出版物提供的音频样本(可在ecs.utdallas.edu/loizou/speech/noizeus/clean.zip
找到)。
wit.ai
API 许可证规定,该工具可免费使用,但上传到其服务器的音频用于调整其语音转录工具。
我们现在将尝试转录sp02.wav
音频样本,执行以下步骤:
- 第一步是注册
wit.ai
帐户。请注意以下截图中显示的 API:
- 第一步是安装 requests 库。可以按以下方式安装:
pip3 install requests
- 根据
wit.ai
的文档,我们需要向我们的请求添加自定义标头,其中包括 API 密钥(用您的帐户中的令牌替换$TOKEN
)。我们还需要在标头中指定文件格式。在这种情况下,它是一个.wav
文件,采样频率为 8000 Hz:
import requests if __name__ == "__main__": url = 'https://api.wit.ai/speech?v=20161002' headers = {"Authorization": "Bearer $TOKEN", "Content-Type": "audio/wav"}
- 为了转录音频样本,我们需要将音频样本附加到请求体中:
files = open('sp02.wav', 'rb') response = requests.post(url, headers=headers, data=files) print(response.status_code) print(response.text)
- 将所有这些放在一起,我们得到了这个:
#!/usr/bin/python3 import requests if __name__ == "__main__": url = 'https://api.wit.ai/speech?v=20161002' headers = {"Authorization": "Bearer $TOKEN", "Content-Type": "audio/wav"} files = open('sp02.wav', 'rb') response = requests.post(url, headers=headers, data=files) print(response.status_code) print(response.text)
前面的代码示例可与本章一起下载,文件名为wit_ai.py
。尝试执行前面的代码示例,它应该会转录音频样本:sp02.wav
。我们有以下代码:
200 { "msg_id" : "fae9cc3a-f7ed-4831-87ba-6a08e95f515b", "_text" : "he knew the the great young actress", "outcomes" : [ { "_text" : "he knew the the great young actress", "confidence" : 0.678, "intent" : "DataQuery", "entities" : { "value" : [ { "confidence" : 0.7145905790744499, "type" : "value", "value" : "he", "suggested" : true }, { "confidence" : 0.5699616515542044, "type" : "value", "value" : "the", "suggested" : true }, { "confidence" : 0.5981701138805214, "type" : "value", "value" : "great", "suggested" : true }, { "confidence" : 0.8999612482250062, "type" : "value", "value" : "actress", "suggested" : true } ] } } ], "WARNING" : "DEPRECATED" }
音频样本包含以下录音:他知道那位年轻女演员的技巧。根据wit.ai
API,转录为他知道了那位年轻女演员。词错误率为 22%(en.wikipedia.org/wiki/Word_error_rate
)。
自动化路由任务
在这一部分,我们将讨论如何在 Python 中自动化路由任务。我们举了两个例子,它们展示了树莓派 Zero 作为个人助手的能力。第一个例子涉及改善通勤,而第二个例子则是帮助提高词汇量。让我们开始吧。
改善日常通勤
许多城市和公共交通系统已经开始向公众分享数据,以增加透明度并提高运营效率。交通系统已经开始通过 API 向公众分享公告和交通信息。这使任何人都能开发提供给通勤者信息的移动应用。有时,这有助于缓解公共交通系统内的拥堵。
这个例子是受到一位朋友的启发,他追踪旧金山共享单车站点的自行车可用性。在旧金山湾区,有一个自行车共享计划,让通勤者可以从交通中心租一辆自行车到他们的工作地点。在像旧金山这样拥挤的城市,特定站点的自行车可用性会根据一天的时间而波动。
这位朋友想要根据最近的共享单车站点的自行车可用性来安排他的一天。如果站点上的自行车非常少,这位朋友更喜欢早点出发租一辆自行车。他正在寻找一个简单的技巧,可以在自行车数量低于某个阈值时向他的手机推送通知。旧金山的共享单车计划在feeds.bayareabikeshare.com/stations/stations.json
上提供了这些数据。
让我们回顾一下构建一个简单的例子,可以使其向移动设备发送推送通知。为了发送移动推送通知,我们将使用If This Then That(IFTTT)——这是一个使您的项目连接到第三方服务的服务。
在这个例子中,我们将解析以 JSON 格式可用的数据,检查特定站点的可用自行车数量,如果低于指定的阈值,就会触发手机设备上的通知。
让我们开始吧:
- 第一步是从共享单车服务中检索自行车的可用性。这些数据以 JSON 格式在
feeds.bayareabikeshare.com/stations/stations.json
上提供。数据包括整个网络的自行车可用性。 - 每个站点的自行车可用性都有一些参数,比如站点 ID、站点名称、地址、可用自行车数量等。
- 在这个例子中,我们将检索旧金山
Townsend at 7th
站点的自行车可用性。站点 ID 是65
(在浏览器中打开前面提到的链接以找到id
)。让我们编写一些 Python 代码来检索自行车可用性数据并解析这些信息:
import requests BIKE_URL = http://feeds.bayareabikeshare.com/stations /stations.json # fetch the bike share information response = requests.get(BIKE_URL) parsed_data = response.json()
第一步是使用GET
请求(通过requests
模块)获取数据。requests
模块提供了内置的 JSON 解码器。可以通过调用json()
函数来解析 JSON 数据。
- 现在,我们可以遍历站点的字典,并通过以下步骤找到
Townsend at 7th
站点的自行车可用性: - 在检索到的数据中,每个站点的数据都附带一个 ID。问题站点的 ID 是
65
(在浏览器中打开之前提供的数据源 URL 以了解数据格式;数据的片段如下截图所示):
使用浏览器获取的自行车共享数据源的片段
- 我们需要遍历数值并确定站点
id
是否与Townsend at 7th
的匹配:
station_list = parsed_data['stationBeanList'] for station in station_list: if station['id'] == 65 and station['availableBikes'] < 2: print("The available bikes is %d" % station ['availableBikes'])
如果站点上的自行车少于2
辆,我们会向我们的移动设备推送移动通知。
- 为了接收移动通知,您需要安装IF by IFTTT应用程序(适用于苹果和安卓设备)。
- 我们还需要在 IFTTT 上设置一个配方来触发移动通知。在
ifttt.com/
注册一个账户。
IFTTT 是一个服务,可以创建连接设备到不同应用程序并自动化任务的配方。例如,可以将树莓派 Zero 跟踪的事件记录到您的 Google Drive 上的电子表格中。
IFTTT 上的所有配方都遵循一个通用模板——如果这样,那么那样,也就是说,如果发生了特定事件,那么就会触发特定的动作。例如,我们需要创建一个 applet,以便在收到 web 请求时触发移动通知。
- 您可以使用您的帐户下拉菜单开始创建一个 applet,如下截图所示:
开始在 IFTTT 上创建一个配方
- 它应该带您到一个配方设置页面(如下所示)。点击这个并设置一个传入的 web 请求:
点击这个
- 选择 Maker Webhooks 频道作为传入触发器:
选择 Maker Webhooks 频道
- 选择接收 web 请求。来自树莓派的 web 请求将作为触发器发送移动通知:
选择接收 web 请求
- 创建一个名为
mobile_notify
的触发器:
创建一个名为 mobile_notify 的新触发器
- 现在是时候为传入触发器创建一个动作了。点击那个。
点击这个
- 选择通知:
选择通知
- 现在,让我们格式化我们想要在设备上收到的通知:
为您的设备设置通知
- 在移动通知中,我们需要接收自行车共享站点上可用自行车的数量。点击+ Ingredient 按钮,选择
Value1
。
格式化消息以满足您的需求。例如,当树莓派触发通知时,希望以以下格式收到消息:该回家了!Townsend & 7th 只有 2 辆自行车可用!
- 一旦您对消息格式满意,选择创建动作,您的配方就应该准备好了!
创建一个配方
- 为了在我们的移动设备上触发通知,我们需要一个 URL 来进行
POST
请求和一个触发键。这在您的 IFTTT 帐户的 Services | Maker Webhooks | Settings 下可用。
触发器可以在这里找到:
Python 物联网入门指南(五)(4)https://developer.aliyun.com/article/1507236