树莓派+阿里云IoT人脸识别场景实战

本文涉及的产品
对象存储 OSS,20GB 3个月
对象存储 OSS,恶意文件检测 1000次 1年
简介: 树莓派+阿里云IoT人脸识别场景实战

1.整体架构

基于阿里云的Serverless架构

2.阿里云产品

IoT平台:https://www.aliyun.com/product/iot

函数计算:https://www.aliyun.com/product/fc

表格存储:https://www.aliyun.com/product/ots

OSS存储:https://www.aliyun.com/product/oss

人脸识别:https://data.aliyun.com/product/face

3.设备采购

名称 图片 购买
摄像头 1535443297032-5e1393f0-6a8c-48f3-bc41-a5 淘宝
树莓派 1535443375085-a5ca4389-931f-4967-b08c-4e 淘宝

4.树莓派设备端开发

4.1 Enable Camera

image.png | left | 300x273.015873015873

4.2 目录结构

  1. 在/home/pi目录下创建 iot文件夹,
  2. 在/home/pi/iot创建 photos文件夹,iot.cfg配置文件,iot.py文件

image.png | left | 400x252.38095238095238

4.3 Python3程序

4.3.1 安装依赖

pip3 install oss2
pip3 install picamera
pip3 install aliyun-python-sdk-iot-client

4.3.2 iot.cfg配置文件

[IOT]
productKey = xxx
deviceName = xxx
deviceSecret = xxx

[OSS]
ossAccessKey = xxx
ossAccessKeySecret = xxx
ossEndpoint = xxx
ossBucketId = xxx

4.3.3 iot.py应用程序

#!/usr/bin/python3
# -*- coding: utf-8 -*-
import oss2
from picamera import PiCamera
import time
import aliyunsdkiotclient.AliyunIotMqttClient as AliyunIot
import configparser

config = configparser.ConfigParser()
config.read('iot.cfg')

# IoT
PRODUCE_KEY = config['IOT']['productKey']
DEVICE_NAME = config['IOT']['deviceName']
DEVICE_SECRET = config['IOT']['deviceSecret']

HOST = PRODUCE_KEY + '.iot-as-mqtt.cn-shanghai.aliyuncs.com'
SUBSCRIBE_TOPIC = "/" + PRODUCE_KEY + "/" + DEVICE_NAME + "/control";
# oss
OSS_AK = config['OSS']['ossAccessKey']
OSS_AK_SECRET = config['OSS']['ossAccessKeySecret']
OSS_ENDPOINT = config['OSS']['ossEndpoint']
OSS_BUCKET_ID = config['OSS']['ossBucketId']

auth = oss2.Auth(OSS_AK, OSS_AK_SECRET)
bucket = oss2.Bucket(auth, OSS_ENDPOINT, OSS_BUCKET_ID)

camera = PiCamera()
camera.resolution = (720,480)

# Take a photo first, then upload photo to oss
def take_photo():
    ticks = int(time.time())
    fileName = 'raspi%s.jpg' % ticks
    filePath = '/home/pi/iot/photos/%s' % fileName
    # take a photo
    camera.capture(filePath)
    # upload to oss
    bucket.put_object_from_file('piPhotos/'+fileName, filePath)


def on_connect(client, userdata, flags, rc):
    print('subscribe '+SUBSCRIBE_TOPIC)
    client.subscribe(topic=SUBSCRIBE_TOPIC)


def on_message(client, userdata, msg):
    print('receive message topic :'+ msg.topic)
    print(str(msg.payload))
    take_photo()


if __name__ == '__main__':
    client = AliyunIot.getAliyunIotMqttClient(PRODUCE_KEY,DEVICE_NAME, DEVICE_SECRET, secure_mode=3)
    client.on_connect = on_connect
    client.on_message = on_message
    client.connect(host=HOST, port=1883, keepalive=60)
    # loop
    client.loop_forever()

5.函数计算开发

5.1 index.js应用程序

const request = require('request');
const url = require('url');
const crypto = require('crypto');
const TableStore = require('tablestore');
const co = require('co');
const RPCClient = require('@alicloud/pop-core').RPCClient;

const config = require("./config");

//iot client
const iotClient = new RPCClient({
    accessKeyId: config.accessKeyId,
    secretAccessKey: config.secretAccessKey,
    endpoint: config.iotEndpoint,
    apiVersion: config.iotApiVersion
});
//ots client
const otsClient = new TableStore.Client({
    accessKeyId: config.accessKeyId,
    secretAccessKey: config.secretAccessKey,
    endpoint: config.otsEndpoint,
    instancename: config.otsInstance,
    maxRetries: 20
});

const options = {
    url: config.dtplusUrl,
    method: 'POST',
    headers: {
        'Accept': 'application/json',
        'Content-type': 'application/json'
    }
};

module.exports.handler = function(event, context, callback) {

    var eventJson = JSON.parse(event.toString());

    try {
        var imgUrl = config.ossEndpoint + eventJson.events[0].oss.object.key;

        options.body = JSON.stringify({ type: 0, image_url: imgUrl });
        options.headers.Date = new Date().toUTCString();
        options.headers.Authorization = makeDataplusSignature(options);

        request.post(options, function(error, response, body) {

            console.log('face/attribute response body' + body)
            const msg = parseBody(imgUrl, body)
            //
            saveToOTS(msg, callback);

        });
    } catch (err) {
        callback(null, err);
    }
};

parseBody = function(imgUrl, body) {

    body = JSON.parse(body);
    //face_rect [left, top, width, height],
    const idx = parseInt(10 * Math.random() % 4);
    const age = (parseInt(body.age[0])) + "岁";
    const expression = (body.expression[0] == "1") ? config.happy[idx] : config.normal[idx];
    const gender = (body.gender[0] == "1") ? "帅哥" : "靓女";
    const glass = (body.glass[0] == "1") ? "戴眼镜" : "火眼金睛";

    return {
        'imgUrl': imgUrl,
        'gender': gender,
        'faceRect': body.face_rect.join(','),
        'glass': glass,
        'age': age,
        'expression': expression
    };
}

//pub msg to WebApp by IoT
iotPubToWeb = function(payload, cb) {
    co(function*() {
        try {
            //创建设备
            var iotResponse = yield iotClient.request('Pub', {
                ProductKey: config.productKey,
                TopicFullName: config.topicFullName,
                MessageContent: new Buffer(JSON.stringify(payload)).toString('base64'),
                Qos: 0
            });
        } catch (err) {
            console.log('iotPubToWeb err' + JSON.stringify(err))
        }

        cb(null, payload);
    });
}

saveToOTS = function(msg, cb) {

    var ots_data = {
        tableName: config.tableName,
        condition: new TableStore.Condition(TableStore.RowExistenceExpectation.IGNORE, null),

        primaryKey: [{ deviceId: "androidPhoto" }, { id: TableStore.PK_AUTO_INCR }],

        attributeColumns: [
            { 'imgUrl': msg.imgUrl },
            { 'gender': msg.gender },
            { 'faceRect': msg.faceRect },
            { 'glass': msg.glass },
            { 'age': msg.age },
            { 'expression': msg.expression }
        ],

        returnContent: { returnType: TableStore.ReturnType.Primarykey }
    }

    otsClient.putRow(ots_data, function(err, data) {

        iotPubToWeb(msg, cb);
    });
}

makeDataplusSignature = function(options) {

    const md5Body = crypto.createHash('md5').update(new Buffer(options.body)).digest('base64');

    const stringToSign = "POST\napplication/json\n" + md5Body + "\napplication/json\n" + options.headers.Date + "\n/face/attribute"
    // step2: 加密 [Signature = Base64( HMAC-SHA1( AccessSecret, UTF-8-Encoding-Of(StringToSign) ) )]
    const signature = crypto.createHmac('sha1', config.secretAccessKey).update(stringToSign).digest('base64');

    return "Dataplus " + config.accessKeyId + ":" + signature;
}

5.2 config.js配置文件

module.exports = {
    accessKeyId: '账号ak',
    secretAccessKey: '账号ak secret',
    iotEndpoint: 'https://iot.cn-shanghai.aliyuncs.com',
    iotApiVersion: '2018-01-20',
    productKey: 'web大屏产品pk',
    topicFullName: 'web大屏订阅识别结果的topic',

//可选,如果不保存结果,不需要ots
    otsEndpoint: 'ots接入点',
    otsInstance: 'ots实例',
    tableName: 'ots结果存储表',
}

6. Web端App开发

<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>阿里云IoT</title>
    <style type="text/css">
    body {
        line-height: 1.6;
        font-family: Arial, Helvetica, sans-serif;
        margin: 0;
        padding: 0;
        background: url(http://iot-face.oss-cn-shanghai.aliyuncs.com/iot-face-yq.png) no-repeat;
        background-color: #202124;
    }

    .face-msg {
        display: inline;
        font-size: 32px;
        color: #5FFFF8;
        padding: 30px 160px 0px 60px;
    }
    </style>
</head>

<body>
    <div style="padding: 190px 10px 0px 360px;">
        <div class="face-msg" id='glass' style="color: #5FFFF8"></div>
        <div class="face-msg" id='gender' style="color: #FF5FE5"></div>
        <div class="face-msg" id='age' style="color: #FFDD5F"></div>
        <div class="face-msg" id='expression' style="color: #FC4D4D"></div>
    </div>
    <!-- -->
    <div style="position: relative;padding: 145px 10px 0px 165px;">
        <div style="position: absolute;">
            <canvas id="myCanvas" width="720px" height="480px"></canvas>
        </div>
        <img id='imageUrl' src="" width="720px" height="480px" />
    </div>
    <script type="text/javascript" src="http://iot-face.oss-cn-shanghai.aliyuncs.com/zepto.min.js"></script>
    <script src="http://iot-face.oss-cn-shanghai.aliyuncs.com/mqttws31.min.js" type="text/javascript"></script>
    <script type="text/javascript">

    $(document).ready(function() {

        initMqtt();
    });

    var client;

    function initMqtt() {
        //模拟设备参数
        var mqttClientId = Math.random().toString(36).substr(2);
        client = new Paho.MQTT.Client("public.iot-as-mqtt.cn-shanghai.aliyuncs.com", 443, mqttClientId);

        // set callback handlers
        var options = {
            useSSL: false,
            userName: '替换iotId',
            password: '替换iot token',
            keepAliveInterval: 60,
            onSuccess: onConnect,
            onFailure: function(e) {
                console.log(e);
            }
        };

        client.onConnectionLost = onConnectionLost;
        client.onMessageDelivered = onMessageDelivered;
        client.onMessageArrived = onMessageArrived;

        // connect the client
        client.connect(options);
    }

    // called when the client connects
    function onConnect() {
        // Once a connection has been made, make a subscription
        client.subscribe("替换订阅数据更新topic");
    }

    // called when the client loses its connection
    function onConnectionLost(responseObject) {
        if (responseObject.errorCode !== 0) {
            console.error("onConnectionLost:", responseObject);
        }
    }

    function onMessageArrived(message) {
        fillData(JSON.parse(message.payloadString))
    }

    function onMessageDelivered(message) {
        console.log("onMessageDelivered: [" + message.destinationName + "] --- " + message.payloadString);
    }

    function fillData(data) {

        $("#age").html(data.age);
        $("#expression").html(data.expression);
        $("#gender").html(data.gender);
        $("#glass").html(data.glass);

        $("#imageUrl").attr("src", data.imgUrl);

        var rect = data.faceRect.split(","); //"270,22,202,287"

        var canvas = document.getElementById("myCanvas");
        var ctx = canvas.getContext("2d");
        ctx.clearRect(0, 0, canvas.width, canvas.height);
        ctx.strokeStyle = '#03A9F4';
        ctx.lineWidth = 2;

        ctx.beginPath();
        ctx.rect(rect[0], rect[1], rect[2], rect[3]);
        ctx.stroke();
    };
    </script>
</body>

</html>

7. 拍照指令触发器

/**
 * package.json 添加依赖:"@alicloud/pop-core": "1.5.2"
 */
const co = require('co');
const RPCClient = require('@alicloud/pop-core').RPCClient;

const options = {
    accessKey: "替换ak",
    accessKeySecret: "替换ak Secret",
};

//1.初始化client
const client = new RPCClient({
    accessKeyId: options.accessKey,
    secretAccessKey: options.accessKeySecret,
    endpoint: 'https://iot.cn-shanghai.aliyuncs.com',
    apiVersion: '2018-01-20'
});

const params = {
    ProductKey: "a1p35XsaOS7",
    TopicFullName: "相机指令topic",
    MessageContent: new Buffer('{"action":"takephoto"}').toString('base64'),
    Qos: "0"
};

co(function*() {
    try {
        //3.发起API调用
        const response = yield client.request('Pub', params);
        console.log(JSON.stringify(response));
    } catch (err) {
        console.log(err);
    }
});

IoT物联网技术 公共账号

1526534749776-9c13a944-f5bd-4a1a-981c-96

相关实践学习
基于函数计算一键部署掌上游戏机
本场景介绍如何使用阿里云计算服务命令快速搭建一个掌上游戏机。
建立 Serverless 思维
本课程包括: Serverless 应用引擎的概念, 为开发者带来的实际价值, 以及让您了解常见的 Serverless 架构模式
相关文章
|
1月前
|
机器学习/深度学习 人工智能 算法
工智能 - 人脸识别:发展历史、技术全解与实战
工智能 - 人脸识别:发展历史、技术全解与实战
22 1
|
3月前
|
人工智能 API 数据安全/隐私保护
Azure AI - Azure人脸识别任务概述与技术实战
Azure AI - Azure人脸识别任务概述与技术实战
147 1
|
8天前
|
存储 算法 Linux
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
【实战项目】网络编程:在Linux环境下基于opencv和socket的人脸识别系统--C++实现
24 6
|
1月前
|
存储 编解码 缓存
购买阿里云服务器如何选择实例?根据业务场景与细分场景选择实例规格
对于很多初次购买阿里云服务器的用户来说,面对众多可选择的云服务器实例规格,往往不知道如何选择,不同实例规格适用于不同的业务场景,本文为大家汇总了不同业务场景和细分场景下应该选择的主要实例规格,以及这些实例规格的主要性能和适用场景,如果你不知道如何选择阿里云服务器的实例规格,不妨根据自己的场景参考本文所推荐的主要实例规格来选择。
购买阿里云服务器如何选择实例?根据业务场景与细分场景选择实例规格
|
25天前
|
机器学习/深度学习 算法 PyTorch
【PyTorch实战演练】深入剖析MTCNN(多任务级联卷积神经网络)并使用30行代码实现人脸识别
【PyTorch实战演练】深入剖析MTCNN(多任务级联卷积神经网络)并使用30行代码实现人脸识别
46 2
|
28天前
|
存储 SQL 数据管理
阿里云数据库 SelectDB 内核 Apache Doris 如何基于自增列满足高效字典编码等典型场景需求|Deep Dive 系列
自增列的实现,使得 Apache Doris 可以在处理大规模时展示出更高的稳定性和可靠性。通过自增列,用户能够高效进行字典编码,显著提升了字符串精确去重以及查询的性能。使用自增列作为主键来存储明细数据,可以完美的解决明细数据更新的问题。同时,基于自增列,用户可以实现高效的分页机制,轻松应对深分页场景,有效过滤掉大量非必需数据,从而减轻数据库的负载压力,为用户带来了更加流畅和高效的数据处理体验。
|
1月前
|
边缘计算 专有云 虚拟化
阿里云神龙在智慧办公场景下的特点
阿里云神龙在智慧办公场景下的特点
|
1月前
|
存储 人工智能 安全
阿里云第八代云服务器实例通用型g8i实例性能和适用场景介绍
随着云计算技术的不断演进,阿里云作为国内领先的云服务提供商,持续推出创新的云服务器实例以满足不同用户的需求。近日,阿里云宣布其第八代云服务器ECS g8i实例已经完成全新升级。g8i实例采用CIPU+飞天技术架构,并搭载最新的Intel 第五代至强可扩展处理器(代号EMR),不仅性能得到大幅提升,同时还拥有AMX加持的AI能力增强,以及全球范围内率先支持的TDX机密虚拟机能力。这些特性使得g8i实例在AI增强和全面安全防护两大方面表现出色,尤其适用于在线音视频及AI相关应用。
阿里云第八代云服务器实例通用型g8i实例性能和适用场景介绍
|
3月前
|
存储 人工智能 安全
阿里云企业成长解决方案,含通用、企业上云、企业服务、教育等多场景
在数字化时代,企业的成长离不开云计算技术的支持。阿里云作为领先的云服务提供商,推出了全面的企业成长解决方案,涵盖通用场景、企业上云、新零售、企业服务、教育、游戏、医疗健康、文化传媒和工业制造等多个行业。这些解决方案旨在帮助企业轻松应对各种挑战,实现数字化转型和升级。
阿里云企业成长解决方案,含通用、企业上云、企业服务、教育等多场景
|
3月前
|
算法 计算机视觉 Python
python实战演练之电梯人脸识别
python实战演练之电梯人脸识别

热门文章

最新文章