在这个项目,将使用一个名为:OpenALPR(自动许可证位置识别)的软件,该软件具有一个API,可用于根据图像识别车牌和汽车模型。基于树莓派作为原型试验,有兴趣的可以自行二次开发。
以下来官方GitHub简介机翻
OpenALPR是一个开源的自动车牌识别库,用C++编写,具有C#,Java,Node,.js Go和Python中的绑定。该库分析图像和视频流以识别车牌。输出是任何车牌字符的文本表示形式。在此处查看实时在线演示:http://www.openalpr.com/demo-image.html
应用在树莓派上的案例可以参考这里:开源车牌识别项目,OpenALPR
概述
该项目分为两部分。
- 首先使用OpenALPR和Node-RED识别汽车;
- 然后将根据检测到的汽车触发一个事件(例如,在检测到你的汽车到达家时打开车库);
原理流程如下:
在这个例子中,PIR运动传感器负责检测汽车是否到达家,使用其他类型的传感器其实也可以,可以按实际情况选择,例如:
霍尔效应传感器:当汽车靠近时,感知磁场的变化;
超声波传感器:检测与物体的距离;
主动红外探测器:通过检测红外光的反射来检测物体的存在。
当传感器检测到运动时,树莓派相机会拍照。之后,树莓派会向OpenALPR发送请求并识别汽车照片。然后,OpenALPR API 返回汽车详细信息,例如:车牌号、型号、颜色和结果的置信度。
识别汽车后,我们将进行一些验证,如果我们找到授权汽车,我们将触发一个事件(例如,可以打开车库),流程图:
在OpenALPR识别汽车后,将检查车牌和汽车模型是否匹配。如果它们匹配,将检查该汽车是否在授权车辆列表中。如果是,我们就触发一个事件。例如:打开车库。之后,我们等待一段时间,直到汽车进入车库。然后,你需要添加几个验证来检查汽车是否已经进入车库。如果是,你可以关闭车库。
先决条件
在开始试验本项目前,你应该熟悉树莓派入门的使用,并对树莓派有一定了解,至少学会使用电平触发LED,进行本项目实验的大概需要的条件如下:
- 你应该学会在树莓派中安装Raspbian或Raspbian Lite操作系统,至于怎么安装,请自行百度基础教程
- 项目会用到使用树莓派相机V2模块,建议参考官网:树莓派相机V2模块指南
- 需要在 Pi 上安装 Node-RED,详情可以参考我之前写的教程:Node-Red基础入门
硬件准备
硬件名称 |
数量 |
单位 |
树莓派开发板(本例使用2B/3B) |
1 |
块 |
树莓派相机 |
1 |
个 |
红外热释人体感应模块(推荐HC-SR501) |
1 |
个 |
220/330电阻 |
1 |
个 |
LED |
1 |
个 |
注意:目前,这里不是真的直接拿道闸和车库门测试,只需要用LED来观察电平即可,LED用来模拟事件触发,或者你也可以使用继电器模块来模拟。
连接相机模块到树莓派
如图:
接线
按网上一般的红外热释示例项目接线即可,本项目重点在于软件端,(画图软件:fritzing)如图:
准备好树莓派并配置Node-RED软件后,就可以继续了。
在Node-Red安装树莓派相机模块
安装
sudo npm install -g node-red-contrib-camerapi
修改照片储存路径
sudo nano /root/.node-red/settings.js
编辑。
- 找到
httpStatic
按需要修改httpStatic: '/home/pi/Pictures/
Node-RED Dashboard上使用树莓派相机
在 Node-RED 上创建一个选项卡和一个组来添加仪表板小组件。按照下一个说明创建选项卡和组(见下图):
- 在 Node-RED 窗口的右上角,你有一个名为dashboard的选项卡。
- 选择该tab (1)。要将选项卡添加到用户界面,请单击 +tab(2)
- 创建后,可以通过单击编辑按钮edit(3)
你可以编辑选项卡的名称并更改其图标:
创建节点-RED 流
在创建流之前,请确保具有 camerapi takephoto 节点,如下图所示。如果没有该节点,先检查是否已按照上述说明进行操作。
在创建流之前,请确保你具有 camerapi takephoto节点,如下图所示。如果没有该节点,请检查你是否已按照上述安装树莓派相机节点部分中的说明进行操作。
首先,将3个节点拖到流中:template、camerapi takephoto、debug.
模板节点
然后,编辑模板节点,如下图所示将模板代码复制并粘贴到图中位置。
<script>
var value = "1";
// or overwrite value in your callback function ...
this.scope.action = function() { return value; }
function updateF() {
var source = '/photo1.JPEG',
timestamp = (new Date()).getTime(),
newUrl = source + '?_=' + timestamp;
document.getElementById("photo").src = newUrl;
}
</script>
<md-button ng-click="send({payload:action()})" onclick="setTimeout(updateF, 2500);" style="padding:40px; margin-bottom: 40px;" >
<ui-icon icon="camera"></ui-icon>
Take a photo<br>
</md-button>
<div style="margin-bottom:40px;">
<img src="/photo1.JPEG" id="photo" width="100%" height="100%">
</div>
此 JavaScript 代码会在拍摄新照片时自动更新 Node-RED 页面
Camerapi Takephoto 节点
最后,使用以下属性编辑 camerapi takephoto 节点:
注意:
-
1:不要忘记将正确的文件路径添加到节点,包括最后一个正斜杠 - /home/pi/Pictures/
-
2:每次打开camerpi takephoto节点时,它都会将文件默认路径更改为yes。因此,请确保每次打开节点时都选择正确的属性。
-
3:当你拍摄新照片时,它将以名称photo1保存在你选择的目录中。JPEG。每次拍摄新照片时,Node-RED 都会覆盖现有照片,因为它们具有相同的名称。
连接节点
连接节点,如下图所示。
最后,按“部署”按钮保存所有更改。
到此为止,Node-RED 应用程序已准备好。进入浏览器访问 UI:http://Your_RPi_IP_address:1880/ui
OpenALPR
OpenALPR是一个开源的自动车牌识别库,用C++编写,具有C#,Java,Node,.js Go和Python的绑定。他们还有OpenALPR Cloud API,这是一个在云中运行的Web服务,可以分析车辆的图像,并通过车牌,型号,颜色等进行响应。OpenALPR Cloud API有一项免费服务,每月最多允许2000次免费识别。
注意:你可以使用的云API,可以安装他们的开源软件并使用他们的Python集成来编写Python脚本来分析无限的图像。这样就不需要使用他们的云服务,并且每月不限于2000个请求。
所支持的国家车牌,见OpenALPR官网
创建账户
要开始使用OpenALPR Cloud API,可以创建一个免费帐户。完成帐户创建后,访问以下页面:
打开Cloud API(云API)选项卡以访问的Secret Key(密钥),需要它来向 API 发出请求。
把的密钥保存在安全的地方,接下来会用到。
测试相机模块和OpenALPR服务
首先,你应该首先使用Pi Camera和OpenALPR服务识别你的汽车。因此,请从提供的示例流开始,该示例流拍摄照片并向 OpeALPR 云 API 发出请求以识别你的汽车。要导入提供的 Node-RED 流,请转到 :GitHub 存储库或单击下图查看原始文件,然后复制提供的代码。
[{"id":"b75c360b.5cfb68","type":"exec","z":"edbc86db.6e9fb8","command":"sudo curl -X POST \"https://api.openalpr.com/v2/recognize?secret_key=Your_Secret_Key&recognize_vehicle=1&country=eu&return_image=0&topn=10\" -F image=@/home/pi/Pictures/car-photo.jpeg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"cURL POST","x":744.5,"y":1823,"wires":[["90e5a95a.7db098"],[],[]]},{"id":"90e5a95a.7db098","type":"json","z":"edbc86db.6e9fb8","name":"JSON","pretty":false,"x":891,"y":1810.5,"wires":[["507a78d0.68c218"]]},{"id":"76990845.65cb78","type":"camerapi-takephoto","z":"edbc86db.6e9fb8","filemode":"1","filename":"car-photo.jpeg","filedefpath":"0","filepath":"/home/pi/Pictures/","fileformat":"jpeg","resolution":"3","rotation":"0","fliph":"0","flipv":"0","brightness":"50","contrast":"0","sharpness":"0","imageeffect":"none","name":"Take Photo","x":578.5,"y":1824,"wires":[["b75c360b.5cfb68"]]},{"id":"507a78d0.68c218","type":"debug","z":"edbc86db.6e9fb8","name":"","active":true,"console":"false","complete":"false","x":1042.5,"y":1810,"wires":[]},{"id":"9ba2e4d7.b859a8","type":"inject","z":"edbc86db.6e9fb8","name":"","topic":"","payload":"","payloadType":"date","repeat":"","crontab":"","once":false,"x":422,"y":1824,"wires":[["76990845.65cb78"]]}]
接下来,在“Node-RED”窗口中的右上角,选择菜单,然后转到Import > Clipboard(导入>剪贴板)。然后,粘贴提供的代码并单击导入(Import)。接下来的节点应显示在流中:
配置测试流
导入流程后,需要进行一些更改使其适配。打开Take Photo “拍照”节点:
编辑节点以使其具有与下图所示相同的设置:
File Name: car-photo.jpeg
File default path: No
File Path: /home/pi/Pictures/
重要提示:有时前一个节点可能会覆盖默认设置,确保仔细检查它是否具有正确的设置,然后,单击部署按钮。
准备 OpenALPR Cloud API 请求
双击 cURL POST 节点:
然后,更改Command字段以包含你的密钥和国家/地区代码:
默认情况下:sudo curl -X POST "https://api.openalpr.com/v2/recognize?secret_key=**你的密钥**&recognize_vehicle=1&country=**国家编号**&return_image=0&topn=10" -F image=@/home/pi/Pictures/car-photo.jpeg
将确切的命令复制并粘贴到 cURL POST 节点的命令字段中,然后按 Node-RED 软件中的部署按钮,以使所有更改生效:
测试流
部署流程后测试汽车识别过程。将汽车移动到可以与树莓派摄影的地方:
将摄像头对准汽车,然后点击timestamp节点旁边的正方形以触发流程。
这应该使用你的 Pi 相机拍摄照片,将其保存在 /home/pi/Pictures/car-photo.jpeg
并向云 API 发出请求以识别车牌和型号。它应该在debug窗口中打印 JSON 响应。
了解响应
打开调试窗口,你应该会看到一个对象,其中包含有关 JSON 响应的所有详细信息。结果数组应至少有一个结果(array[1]),否则它可能正在分析没有汽车的照片,或者无法识别汽车(确保在拍照时树莓派相机瞄准汽车)。
单击结果旁边的箭头 results: array[1]以展开对象。你应该在车牌上看到一个车牌对象。以 API 检索的格式保存车牌。在我这里是“61CP-”。你稍后需要用它来识别你的汽车:
将vehicle对象展开object > make_model > 0: object,应该会看到汽车的名称以及 API 如何识别汽车模型。在案例中,将汽车确定为丰田雅力士,置信度为77.2%。保存 API 检索到的确切字符串“toyota_yaris”,因为在下一个流中需要它,API 会以检索的格式保存
如果你的响应返回无效结果,请务必仔细检查以下详细信息:
- Take Photo节点将照片存储在正确的文件路径中:
/home/pi/Pictures/
- 确保相机拍摄的照片很好(访问
/home/pi/Pictures/car-photo
上文件,查看拍摄的照片)
- 查看照片是否可见汽车和车牌,否则API可能无法正确识别汽车
- 确保你在
cURL POST
命令中使用自己的 API 密钥和国家/地区代码输入了正确的命令
汽车牌照识别系统流程
在这一部分中,我们将向流中添加汽车检测和事件触发。当检测到运动时,Pi 相机使用 Pi 相机拍摄照片,并向 OpenALPR 发出请求。然后,根据响应,它将触发一个事件(在本例中,我们将设置一个输出以点亮LED)。
要导入提供的 Node-RED 流,请转到GitHub存储库或单击下图查看原始文件,然后复制提供的代码。
[{"id":"d2b7852a.b05618","type":"exec","z":"edbc86db.6e9fb8","command":"sudo curl -X POST \"https://api.openalpr.com/v2/recognize?secret_key=Your_Secret_Key&recognize_vehicle=1&country=eu&return_image=0&topn=10\" -F image=@/home/pi/Pictures/car-photo.jpeg","addpay":false,"append":"","useSpawn":"false","timer":"","oldrc":false,"name":"cURL POST","x":731,"y":1317,"wires":[["1ffd9483.014b3b"],[],[]]},{"id":"1ffd9483.014b3b","type":"json","z":"edbc86db.6e9fb8","name":"JSON","pretty":false,"x":882.5,"y":1332.5,"wires":[["9753406b.6d08e","5f3c3d58.fd75e4"]]},{"id":"9753406b.6d08e","type":"function","z":"edbc86db.6e9fb8","name":"Identify Car","func":"var carPlate = \"YOUR_CAR_PLATE\";\nvar carModel = \"YOUR_CAR_MODEL\";\n\n//No car or car plate found in photo\nif(msg.payload.results.length === 0) {\n msg.payload=0;\n global.set(\"garageOpen\",\"0\"); \n}\n//If car plate and car model match\nelse if(msg.payload.results[0].plate==carPlate && msg.payload.results[0].vehicle.make_model[0].name==carModel) {\n msg.payload=1;\n global.set(\"garageOpen\",\"1\"); \n}\n//If car plate and car model don't match\nelse {\n msg.payload=0; \n global.set(\"garageOpen\",\"0\"); \n}\n\nreturn msg;\n\n","outputs":1,"noerr":0,"x":292,"y":1521.5,"wires":[["8b530f08.a5dbf"]]},{"id":"3630c78a.035728","type":"camerapi-takephoto","z":"edbc86db.6e9fb8","filemode":"1","filename":"car-photo.jpeg","filedefpath":"0","filepath":"/home/pi/Pictures/","fileformat":"jpeg","resolution":"3","rotation":"0","fliph":"0","flipv":"0","brightness":"50","contrast":"0","sharpness":"0","imageeffect":"none","name":"Take Photo","x":565,"y":1318,"wires":[["d2b7852a.b05618"]]},{"id":"8b530f08.a5dbf","type":"switch","z":"edbc86db.6e9fb8","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"1","vt":"str"},{"t":"eq","v":"0","vt":"str"}],"checkall":"true","outputs":2,"x":432.5,"y":1520,"wires":[["c2bbe2ac.f26ea","8fe08deb.7255e"],["491dea2b.a14d54"]]},{"id":"5f3c3d58.fd75e4","type":"debug","z":"edbc86db.6e9fb8","name":"","active":true,"console":"false","complete":"false","x":1028,"y":1297,"wires":[]},{"id":"4e5c105d.14285","type":"rpi-gpio in","z":"edbc86db.6e9fb8","name":"GPIO4","pin":"7","intype":"tri","debounce":"25","read":false,"x":111,"y":1359,"wires":[["af21a185.21cd4"]]},{"id":"73147f6a.0129e","type":"switch","z":"edbc86db.6e9fb8","name":"","property":"payload","propertyType":"msg","rules":[{"t":"eq","v":"0","vt":"str"},{"t":"eq","v":"1","vt":"str"}],"checkall":"true","outputs":2,"x":418,"y":1359,"wires":[["3630c78a.035728"],["691d92c5.692d5c"]]},{"id":"af21a185.21cd4","type":"function","z":"edbc86db.6e9fb8","name":"Is Garage Open","func":"var garageOpen = global.get(\"garageOpen\"); \n\nif(garageOpen == \"1\"){\n msg.payload = 1;\n}\nelse {\n msg.payload = 0;\n}\n\nreturn msg;","outputs":1,"noerr":0,"x":261.5,"y":1359,"wires":[["73147f6a.0129e"]]},{"id":"c2bbe2ac.f26ea","type":"rpi-gpio out","z":"edbc86db.6e9fb8","name":"GPIO17","pin":"11","set":"","level":"0","freq":"","out":"out","x":919.5,"y":1469,"wires":[]},{"id":"8fe08deb.7255e","type":"delay","z":"edbc86db.6e9fb8","name":"","pauseType":"delay","timeout":"10","timeoutUnits":"seconds","rate":"1","nbRateUnits":"1","rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"x":610,"y":1528,"wires":[["f2cc1ee4.e9841"]]},{"id":"f2cc1ee4.e9841","type":"function","z":"edbc86db.6e9fb8","name":"Close Garage","func":"msg.payload=0; \nglobal.set(\"garageOpen\",\"0\"); \nreturn msg;\n\n","outputs":1,"noerr":0,"x":770,"y":1528,"wires":[["c2bbe2ac.f26ea"]]},{"id":"691d92c5.692d5c","type":"debug","z":"edbc86db.6e9fb8","name":"","active":true,"console":"false","complete":"false","x":558,"y":1366,"wires":[]},{"id":"491dea2b.a14d54","type":"debug","z":"edbc86db.6e9fb8","name":"","active":true,"console":"false","complete":"false","x":607,"y":1585,"wires":[]}]
接下来,在“Node-RED”窗口中的右上角,选择菜单,然后转到Import > Clipboard
配置流
导入流程后,你需要进行一些更改以使其适合你。打开Take Photo 节点:
编辑节点以使其具有与下图所示相同的设
- 文件名:
car-photo.jpeg
- 文件默认路径:
No
- 文件路径:
/home/pi/Pictures/
准备 OpenALPR Cloud API 请求
双击 cURL POST节点:
然后,更改Command字段以包含你的密钥和国家/地区代码:
默认情况下命令:
sudo curl -X POST "https://api.openalpr.com/v2/recognize?secret_key=你的密钥&recognize_vehicle=1&country=你的国家代码&return_image=0&topn=10" -F image=@/home/pi/Pictures/car-photo.jpeg
并在里面添加你之前检索到的密钥和国家/地区代码
将汽车详细信息添加到流程中
打开功能节点 Identify Car以添加汽车的车牌和型号。
将 carPlate和carModel变量替换为你自己的车牌和型号名称(格式与之前检索的格式完全相同)。在我们的例子中,我们得到:
var carPlate = "61CP--";
var carModel = "toyota_yaris";
下图显示了在功能节点上添加车牌和模型的位置:
注意:如果要添加另一个车牌,则需要编辑“识别汽车”功能。声明另一个carPlate2和carModel2
var carPlate2 = " ";
var carModel2= " ";
然后,在 else if
语句之后,添加以下内容:
else if(msg.payload.results[0].plate==carPlate2 && msg.payload.results[0].vehicle.make_model[0].name==carModel2)
{ msg.payload=1; global.set("garageOpen","1");
}
这应该允许你验证两辆车(你可以添加更多)。
添加汽车详细信息后,按Done并点按Deploy按钮:
当汽车到达时,PIR传感器检测运动,Pi摄像头负责拍摄照片,并使用OpenALPR API识别汽车。Node-RED 负责识别你的车牌和车型。然后,它将触发一个事件:它将 GPIO 17 打开几秒钟,然后关闭。这模拟打开/关闭车库门命令。