基于Blinker _ ESP32_CAM与百度云AI开发低成本人脸门禁控制器-Arduino中文社区 - Powered by Discuz!

Arduino中文社区

 找回密码
 立即注册

QQ登录

只需一步,快速开始

查看: 2485|回复: 11

[分享] 基于Blinker_ ESP32_CAM与百度云AI开发低成本人脸门禁控制器

[复制链接]
发表于 2021-12-19 20:47 | 显示全部楼层 |阅读模式
本帖最后由 526598 于 2021-12-19 22:07 编辑

话不多说,先上代码!!!!

  1. #define BLINKER_WIFI
  2. //#define BLINKER_ESP_SMARTCONFIG //自动配网设置

  3. #include <HTTPClient.h>
  4. #include <ArduinoJson.h>
  5. #include <base64.h>
  6. #include <Blinker.h>
  7. #include "ESP32_CAM_SERVER.h"

  8. char auth[] = "Your Device Secret Key";
  9. char ssid[] = "Your WiFi network SSID or name";
  10. char pswd[] = "Your WiFi network WPA password or WEP key";

  11. #define client_id         "************************" //API Key【百度云应用的AK】
  12. #define client_secret     "********************************"//Secret Key【百度云应用的SK】

  13. #define Json_begin        "{"image":""         //Json封装头
  14. //#define Json_end          "","image_type":"BASE64","group_id_list":"......"}" //人脸查找API_Json封装尾
  15. String access_token;
  16. String Group_list_str;
  17. bool setup_camera = false;

  18. #define BUTTON_1 "ButtonKey"
  19. BlinkerButton Button1(BUTTON_1);

  20. //人脸验证程序,图像数据需要经过base64编码后以JSON格式发送
  21. static void Baidu_AI(camera_fb_t* &fb){
  22.   String base64 = base64::encode(fb->buf,fb->len);
  23.   uint16_t len = base64.length();
  24.   HTTPClient http;
  25.   http.begin("https://aip.baidubce.com/rest/2.0/face/v3/search?access_token="+access_token);
  26.   String POST_Code=Json_begin+base64+Json_end;
  27.   http.setReuse(true);
  28.   http.addHeader("Content-Type", "application/x-www-form-urlencoded");
  29.   http.addHeader("Accept","application/json");
  30.   http.addHeader("Content-Length",String(POST_Code.length()));
  31.   http.addHeader("X-Custom-Header", "custom-header-value");
  32.   int httpCode = http.POST(POST_Code);


  33.   if (httpCode > 0) {
  34.     // HTTP header has been send and Server response header has been handled
  35.     Serial.println("验证人脸... ");
  36.     // file found at server
  37.     if (httpCode == HTTP_CODE_OK) {
  38.       String  payload=http.getString();
  39.       DynamicJsonDocument  jsonBuffer(JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2)+strlen(payload.c_str())*sizeof(String));
  40.       DeserializationError error = deserializeJson(jsonBuffer, payload);
  41.       if (error) {
  42.         Serial.print(F("deserializeJson() failed: "));
  43.         BLINKER_LOG(error.c_str());
  44.         http.end();
  45.         return;
  46.       }
  47.       JsonObject reload_Json = jsonBuffer.as<JsonObject>();
  48.       int search_buff_error_code=reload_Json["error_code"].as<int>();
  49.       
  50.       if (search_buff_error_code==0){  
  51.         String search_buff_user_id=reload_Json["result"]["user_list"][0]["user_id"].as<const char*>();
  52.         String search_buff_group_id=reload_Json["result"]["user_list"][0]["group_id"].as<const char*>();
  53.         float search_buff_score=reload_Json["result"]["user_list"][0]["score"].as<float>();
  54.         Serial.print("用户名:"+search_buff_user_id);
  55.         Serial.println("  相似度: "+String(search_buff_score));
  56.         
  57.         Blinker.print("用户名:"+search_buff_user_id);
  58.         Blinker.print("相似度: "+String(search_buff_score));
  59.         if(search_buff_score>=79){
  60.           //官方建议相似度超过80%即可视为验证通过,可以在这里插入控制门禁设备代码
  61.           Blinker.print("门已开启");
  62.           Serial.print("门已开启");
  63.         }
  64.         
  65.       }else{
  66.         Serial.println("未检测到人脸信息!");
  67.       }
  68.     }
  69.   } else {
  70.     //Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
  71.   }
  72.   http.end();

  73.    
  74. }
  75. //获取百度鉴权认证认证token
  76. static void Baidu_AI_token(){
  77.   HTTPClient http;
  78.   Serial.printf("获取百度_AI_token ... ");

  79.   http.begin("https://aip.baidubce.com/oauth/2.0/token");
  80.   http.addHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  81.   
  82.   int httpCode = http.POST("grant_type=client_credentials&client_id="+String(client_id) +"&client_secret="+String(client_secret));
  83.   if (httpCode > 0) {
  84.     // HTTP header has been send and Server response header has been handled

  85.     // file found at server
  86.     if (httpCode == HTTP_CODE_OK) {
  87.       String  payload=http.getString();
  88.       DynamicJsonDocument  jsonBuffer(JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2)+strlen(payload.c_str())*sizeof(String));
  89.       //DynamicJsonDocument  jsonBuffer(20000);
  90.       DeserializationError error = deserializeJson(jsonBuffer, payload);
  91.       if (error) {
  92.         Serial.print(F("deserializeJson() failed: "));
  93.         Serial.println(error.c_str());
  94.         http.end();
  95.         return;
  96.       }
  97.       
  98.       JsonObject reload_Json = jsonBuffer.as<JsonObject>();
  99.       access_token=reload_Json["access_token"].as<const char*>();
  100.       Serial.println("SUCCESS");
  101.       //Serial.print("access_token=");
  102.       //Serial.println(access_token);

  103.     }
  104.   } else {
  105.     Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
  106.   }
  107.   http.end();


  108.   delay(500);
  109. }
  110. //获取用户组列表
  111. static void Baidu_AI_Group_list(){
  112.   HTTPClient http;
  113.   Serial.println("[HTTPS] 获取组列表...");

  114.   http.begin("https://aip.baidubce.com/rest/2.0/face/v3/faceset/group/getlist");
  115.   http.addHeader("Content-Type", "application/json; charset=UTF-8");
  116.   String POST_Code="access_token="+access_token;
  117.   int httpCode = http.POST(POST_Code);
  118.   if (httpCode > 0) {
  119.     Serial.println("[HTTP] 获取用户列表 ... ");
  120.     // HTTP header has been send and Server response header has been handled
  121.     // file found at server
  122.     if (httpCode == HTTP_CODE_OK) {
  123.       String  payload=http.getString();
  124.       int payload_len=strlen(payload.c_str());
  125.       DynamicJsonDocument  group_list_jsonBuffer(JSON_OBJECT_SIZE(3) + JSON_ARRAY_SIZE(2)+payload_len*sizeof(String));
  126.       DeserializationError error = deserializeJson(group_list_jsonBuffer, payload);
  127.       if (error) {
  128.         Serial.print(F("获取用户组列表失败: "));
  129.         Serial.println(error.f_str());
  130.         http.end();
  131.         return;
  132.       }
  133.       //获取组列表
  134.       JsonObject group_list_Json = group_list_jsonBuffer.as<JsonObject>();
  135.       int Group_len=group_list_Json["result"]["group_id_list"].size();
  136.       Serial.print("用户组数量=");
  137.       Serial.println(Group_len);
  138.       int User_list_count=0;
  139.       //http.end();
  140.       if(Group_len>0){  
  141.         Group_list_str=group_list_Json["result"]["group_id_list"][0].as<const char*>();
  142.         for(int i=0;i<Group_len-1;i++){
  143.           Group_list_str=Group_list_str+","+group_list_Json["result"]["group_id_list"][i+1].as<const char*>();
  144.         }
  145.         //Serial.println(Group_list_str);
  146.       }
  147.     }
  148.   } else {
  149.     Serial.printf("[HTTP] ... failed, error: %s\n", http.errorToString(httpCode).c_str());
  150.   }
  151.   http.end();
  152.   delay(500);
  153. }

  154. void button1_callback(const String & state)
  155. {
  156.     digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  157.     BLINKER_LOG("get button state: ", state);
  158.     camera_fb_t *fb = esp_camera_fb_get();
  159.     if(!fb)return;
  160.     //BLINKER_LOG("Got image");
  161.     Baidu_AI(fb);   //人脸验证程序,图像数据需要经过base64编码后以JSON格式发送
  162.     esp_camera_fb_return(fb);
  163.    
  164. }
  165. void dataRead(const String & data)
  166. {
  167.     BLINKER_LOG("Blinker readString: ", data);

  168.     Blinker.vibrate();
  169.    
  170.     uint32_t BlinkerTime = millis();
  171.    
  172.     Blinker.print("millis", BlinkerTime);
  173. }

  174. void setup()
  175. {
  176.     Serial.begin(115200);
  177.     BLINKER_DEBUG.stream(Serial);

  178.     pinMode(LED_BUILTIN, OUTPUT);
  179.     digitalWrite(LED_BUILTIN, LOW);
  180.    
  181.     //Blinker.begin(auth);//自动配网设置
  182.     Blinker.begin(auth,ssid,pswd);
  183.     Blinker.attachData(dataRead);
  184.     Button1.attach(button1_callback);
  185. }
  186. void loop()
  187. {
  188.     Blinker.run();

  189.     if (Blinker.connected() && !setup_camera)
  190.     {
  191.         setupCamera();
  192.         setup_camera = true;

  193.         Blinker.printObject("video", "{"str":"mjpg","url":"http://"+ WiFi.localIP().toString() + ""}");
  194.         if(access_token==NULL){
  195.             BLINKER_LOG("成功连接网络,尝试获取百度AI_token");
  196.             Baidu_AI_token();//获取百度鉴权认证认证token
  197.             Baidu_AI_Group_list();//获取用户组列表
  198.             Serial.println("设备准备就绪可以进行人脸识别 ... ...");
  199.             Blinker.print("设备准备就绪可以进行人脸识别 ... ...");
  200.         }
  201.     }
  202. }
复制代码


DSC_0312.jpg 未标题-2.jpg
主要分以下几个步骤:
一、到百度云 https://cloud.baidu.com/申请账号,产品服务搜索 ”人脸识别“——创建应用——领取免费额度
        应用创建后记录好”API Key“及”Secret Key“——查看人脸库——新建组——新建成员并添加用来比对的照片。
二、在手机上点灯APP添加独立设备并记录新设备SecretKey。
三、填写程序中各密钥(API Key、Secret Key、SecretKey)及WIFI的SSID和密码(有条件的可以做自动配网)。
四、程序刷写到模块后在手机点灯app中添加视频及各辅助模块。

由于本人水平有限本程序没有门禁控制部分,各位参考实际情况酌情填写。
目前发现该程序有以下几点情况:
1、在APP视频控件里有白屏现象,不清楚是视频头不工作还是网络问题,关闭app后重新打开能看到图像
2、通电后等待时间稍长,估计是与连接网络及连接各平台有关
以上如果大家有更好的办法,请多多指教。

发表于 2022-4-9 15:21 | 显示全部楼层
你好 请问这个项目还有其他的工程文件吗
 楼主| 发表于 2022-4-20 08:48 | 显示全部楼层
炸酱面007 发表于 2022-4-9 15:21
你好 请问这个项目还有其他的工程文件吗

没,参考示例>Blinker>Blinker_ESP32_CAM
发表于 2022-4-22 15:29 | 显示全部楼层
526598 发表于 2022-4-20 08:48
没,参考示例>Blinker>Blinker_ESP32_CAM

博主可以给个联系方式么 有点问题想请教一下
发表于 2022-4-22 15:30 | 显示全部楼层
526598 发表于 2022-4-20 08:48
没,参考示例>Blinker>Blinker_ESP32_CAM

为什么我编译的时候总是在 json封装哪里报错 说差一个冒号呢
发表于 2022-4-26 12:19 | 显示全部楼层
缺少库文件,楼主可不可以发下
发表于 2022-4-26 12:35 | 显示全部楼层
缺少ESP32_CAM_SERVER.h库文件
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|Archiver|手机版|Arduino中文社区

GMT+8, 2024-11-28 08:47 , Processed in 0.100038 second(s), 20 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表