本文介绍如何在物联网应用开发(IoT Studio)平台使用树莓派摄像头实现人脸识别功能。即将树莓派摄像头采集的人像,存储到阿里云对象存储(OSS)中,同时,通过设备属性上报获取图片,并调用人脸识别API进行人脸识别后,在钉钉群中推送验证结果。

流程图

流程

物料准备

硬件 说明
树莓派主板 将摄像头和红外线传感器连接到树莓派主板:
  • 将摄像头连接线头插入到树莓派卡槽中
  • 将红外线传感器(PIR)连接线头插入到树莓派GPIO引脚
适用于树莓派的摄像头
红外线传感器

创建对象存储Bucket

本示例中,摄像头拍摄的图像将存储在阿里云对象存储中,因此需为图像存储创建一个存储空间Bucket。开发设备端SDK时,需要配置该Bucket信息。

  1. 登录对象存储控制台

    若您还未开通对象存储服务,请单击立即开通,进入购买页开通服务。对象存储计费,请参见对象存储计费方式

  2. 概览页面,单击右侧的创建Bucket,配置Bucket参数。
    有关创建存储空间的更多详细内容,请参见创建存储空间
    参数 说明
    Bucket名称 自定义Bucket名称。

    Bucket名称仅支持:小写英文字母、数字和连接号(-),且不能以连接号开头或结尾。

    区域 选择您要创建的Bucket所在地域。创建成功后,地域不可更改。
    存储类型 选择为标准存储
    读写权限 本示例中,选择为公共读写。实际使用中,请根据您的实际需要选择。
    同城区域冗余存储 本示例中,选择为关闭。实际使用中,请根据您的实际需要选择。
    实时日志查询 本示例中,选择为不开通。实际使用中,请根据您的实际需要选择。
    Bucket创建后,其概览页会显示Endpoint和域名。Endpoint信息需配置到设备端SDK中。endpoint信息
  3. 测试Bucket。
    1. 在Bucket页,单击文件管理 > 上传文件,上传一张测试图片。
    2. 图片上传后,单击详情按钮,再将文件URL粘贴到浏览器中。浏览器中显示该图片,证明Bucket使用正常。

创建产品和设备

  1. 登录物联网平台控制台
  2. 在左侧导航栏,单击设备管理 > 产品,创建摄像头产品。创建产品
  3. 在产品的产品详情功能定义页签下,添加两个属性。
    标识符 数据类型 数据定义
    people bool 0:没人;1:有人。
    picURL text 数据长度限制:2048字节。
    功能属性
  4. 在左侧导航栏,单击设备,然后创建设备。请参见批量创建设备单个创建设备

设备端SDK开发

因为树莓派基于Python语言,需要配置两个Python SDK: IoT设备端接入SDKOSS文件上传SDK

设备端SDK开发代码示例如下:

  • 引入相关库。
    import aliyunsdkiotclient.AliyunIotMqttClient as iot ##导入阿里云的设备MQTT库,如果import失败需要先pip3 install
    import json
    import multiprocessing
    import time
    import random
    import oss2 ##导入阿里云的OSS库,如果import失败需要先pip3 install oss2
    from picamera import PiCamera ##树莓派的摄像头,系统自带
    import RPi.GPIO as GPIO ##GPIO口,接红外PIR使用
  • OSS Bucket访问授权
    auth = oss2.Auth('**YourAccessKeyId**','**YourAccessKeySecret**') ##OSS的授权,需要您的阿里云账号AccessKey ID和AccessKey Secret,具体查看https://usercenter.console.aliyun.com/#/manage/ak
    bucket = oss2.Bucket(auth,'http://oss-cn-beijing.aliyuncs.com','**YourBucketName**') ##请在OSS控制台,Bucket的概览页查看具体信息
    global picURLtoIoT
    camera = PiCamera()
    camera.resolution = (800,600)  ##拍照分辨率,越高越容易分析,但是上传速度越慢
  • 初始化树莓派。
    def init():
        GPIO.setwarnings(False)
        GPIO.setmode(GPIO.BOARD)
        GPIO.setup(3, GPIO.IN)
        pass
  • 定义图像上传OSS Bucket。
    def take_photo():
        ticks = int(time.time())
        fileName = 'test%s.jpg' % ticks  ##在文件名加入时间戳作为简易加密手段
        filePath = '/home/pi/Pictures/%s' % fileName
        camera.capture(filePath)
        bucket.put_object_from_file('bucket_file_name/%s', fileName) ##在这里改bucket名称
        global picURLtoIoT
        picURLtoIoT = 'http://**您的bucket名称**.oss-cn-shanghai.aliyuncs.com/bucket_file_name/%s' % fileName ##图片存储URL,需替换为您的bucket名称和bucket内文件名称
        print(str(picURLtoIoT))
  • 定义红外线感应器检测到有人时,摄像头拍照,否则休眠5秒。
    def detectPeople():
        if GPIO.input(3) == True:
    take_photo()
        else:
        time.sleep(5)
    
    options = {
        'productKey':'**设备的ProductKey**',
        'deviceName':'**设备的deviceName**',
        'deviceSecret':'**设备的deviceSecret**',
        'port':1883,
        'host':'iot-as-mqtt.cn-shanghai.aliyuncs.com' ##物联网平台域名
    }
    host = options['productKey'] + '.' + options['host']
    
    def on_message(client, userdata, msg):
        topic = '/' + productKey + '/' + deviceName + '/update'
        print(msg.payload)
    
    def on_connect(client, userdata, flags_dict, rc):
        print("Connected with result code " + str(rc))
    
    def on_disconnect(client, userdata, flags_dict, rc):
        print("Disconnected.")
  • 定义设备上报数据到物联网平台。
    def upload_device(client):
        topic = '/sys/'+options['productKey']+'/'+options['deviceName']+'/thing/event/property/post'
        while True:
            payload_json = {
                'id': int(time.time()),
                'params': {
    'people':1 ##物模型里布尔值以0和1的形式上报
                    'picURL': picURLtoIoT,
                },
               'method': "thing.event.property.post"
                }
            print('send data to iot server: ' + str(payload_json))
            client.publish(topic, payload=str(payload_json))
    
    if __name__ == '__main__':
        client = iot.getAliyunIotMqttClient(options['productKey'], options['deviceName'], options['deviceSecret'], secure_mode=3)
        client.on_connect = on_connect
        client.connect(host=host, port=options['port'], keepalive=60)
        p = multiprocessing.Process(target=upload_device, args=(client,))
        p.start()
        detectPeople()
        GPIO.cleanup()
        client.loop_forever()

完整的示例代码,请见本文末附录章节。

创建业务服务

  1. 登录物联网平台控制台,在左侧导航栏,单击IoT Studio > 项目管理
  2. 单击已有项目卡片进入项目,或单击新建项目,创建一个项目。
  3. 在项目详情的产品页,单击关联物联网平台产品,将之前创建的摄像头产品和设备与该项目关联。详细操作请参见关联产品至普通项目
  4. 在项目详情主页,选择业务服务,单击新建,创建一个业务服务。
  5. 在业务逻辑编辑页,单击左侧的节点按钮,服务开发的功能节点将展示在列表中。
  6. 输入页签下,拖拽一个设备触发节点到画布上,触发数据源配置为摄像头产品下设备的属性上报。
    设备触发
  7. 配置一个云市场API节点,并与设备触发节点相连。
    业务配置

    需在阿里云云市场购买人脸识别API。本示例购买的API是艾科瑞特(iCREDIT)_智能人脸识别

    参数 说明
    节点名称 输入节点名称。
    请求方式 在云市场该API购买页,查看请求方式。本示例中,购买的API的请求方式为POST。
    调用地址 在云市场该API购买页,查看该API的调用地址。
    APPCODE 云市场控制台已购买的服务页列表中,查看已购买API的AppCode。
    编码 选择编码方式。
    参数填写 根据云市场该API购买页的请求参数说明,填入请求参数。本示例中,需填入两个参数:
    • IMAGE:图像数据存储的URL。可输入:
      • 静态值:即输入图像在OSS中的存储地址URL。
      • 动态值:配置为动态获取值,本示例动态取值设置为:"IMAGE":"{{query.props.picURL.value}}",即从属性picURL的数据中获取。
    • IMAGE_TYPE0:图像内容为图像数据BASE64编码;1:图像内容为图像文件的URL。本示例采用URL,配置为"IMAGE_TYPE":"1"
  8. 配置一个钉钉机器人。
    钉钉机器人
    参数 说明
    节点名称 输入节点名称
    Webhook 钉钉群机器人的Webhook地址。详细内容请参见创建钉钉机器人
    配置方法 选择为自定义
    消息类型 选择为FeedCard类型
    内容配置
    • 修改消息标题title
    • 修改picURL值为{{query.props.picURL.value}}
  9. 单击页面右上角保存按钮,保存配置。

调试与发布

  1. 单击部署按钮,部署服务。
  2. 部署完成后,单击启动
  3. 调试服务。
    1. 单击调试 > 前往,前往产品的在线调试页。
    2. 选择调试虚拟设备,并启动虚拟设备。
    3. 输入模拟属性值,单击推送
      调试服务
      数据推送成功,钉钉群将收到图片。钉钉群收到图片
  4. 单击发布按钮,发布服务。

附录:设备端SDK代码示例

import aliyunsdkiotclient.AliyunIotMqttClient as iot ##导入阿里云的设备MQTT库,如果import失败需要先pip3 install
import json
import multiprocessing
import time
import random
import oss2 ##导入阿里云的OSS库,如果import失败需要先pip3 install oss2
from picamera import PiCamera ##树莓派的摄像头,系统自带
import RPi.GPIO as GPIO ##GPIO口,接红外PIR使用

auth = oss2.Auth('**YourAccessKeyId**','**YourAccessKeySecret**') ##OSS的授权,需要您的阿里云账号AccessKey ID和AccessKey Secret,具体查看https://usercenter.console.aliyun.com/#/manage/ak
bucket = oss2.Bucket(auth,'http://oss-cn-beijing.aliyuncs.com','**YourBucketName**') ##请在OSS控制台,Bucket的概览页查看具体信息
global picURLtoIoT
camera = PiCamera()
camera.resolution = (800,600)  ##拍照分辨率,越高越容易分析,但是上传速度越慢

##初始化树莓派
def init():
    GPIO.setwarnings(False)
    GPIO.setmode(GPIO.BOARD)
    GPIO.setup(3, GPIO.IN)
    pass

def take_photo():
    ticks = int(time.time())
    fileName = 'test%s.jpg' % ticks  ##在文件名加入时间戳作为简易加密手段
    filePath = '/home/pi/Pictures/%s' % fileName
    camera.capture(filePath)
    bucket.put_object_from_file('bucket_file_name/%s', fileName) ##在这里改bucket名称
    global picURLtoIoT
    picURLtoIoT = 'http://**您的bucket名称**.oss-cn-shanghai.aliyuncs.com/bucket_file_name/%s' % fileName ##图片存储URL,需替换为您的bucket名称和bucket内文件名称
    print(str(picURLtoIoT))

##如果检测到有人则拍照,否则休眠5秒
def detectPeople():
    if GPIO.input(3) == True:
take_photo()
    else:
    time.sleep(5)

options = {
    'productKey':'**设备的ProductKey**',
    'deviceName':'**设备的deviceName**',
    'deviceSecret':'**设备的deviceSecret**',
    'port':1883,
    'host':'iot-as-mqtt.cn-shanghai.aliyuncs.com' ##物联网平台域名
}
host = options['productKey'] + '.' + options['host']

def on_message(client, userdata, msg):
    topic = '/' + productKey + '/' + deviceName + '/update'
    print(msg.payload)

def on_connect(client, userdata, flags_dict, rc):
    print("Connected with result code " + str(rc))

def on_disconnect(client, userdata, flags_dict, rc):
    print("Disconnected.")

##设备上报属性
def upload_device(client):
    topic = '/sys/'+options['productKey']+'/'+options['deviceName']+'/thing/event/property/post'
    while True:
        payload_json = {
            'id': int(time.time()),
            'params': {
'people':1 ##物模型里布尔值以0和1的形式上报
                'picURL': picURLtoIoT,
            },
           'method': "thing.event.property.post"
            }
        print('send data to iot server: ' + str(payload_json))
        client.publish(topic, payload=str(payload_json))

if __name__ == '__main__':
    client = iot.getAliyunIotMqttClient(options['productKey'], options['deviceName'], options['deviceSecret'], secure_mode=3)
    client.on_connect = on_connect
    client.connect(host=host, port=options['port'], keepalive=60)
    p = multiprocessing.Process(target=upload_device, args=(client,))
    p.start()
    detectPeople()
    GPIO.cleanup()
    client.loop_forever()