微信小程序-人脸检测-眨眼驱动ESP32蓝牙设备灯_如何在微信小程序实现眨眼检测?-程序员宅基地

技术标签: 微信小程序  小程序  

前面2篇文章已经写了具体的人脸检测和蓝牙
这里直接结合,只列js 代码,剩下的其他代码在另外文章里面
https://blog.csdn.net/walle167/article/details/136261993
https://blog.csdn.net/walle167/article/details/136261919
上代码


import bleBehavior from './ble'

Component({
    
  behaviors: [bleBehavior],
  session: undefined, // 全局的VKsession对象
  data:{
    
    originx:"1%",
    originy:"1%",
    eyeLetfHeight:"100%",
    eyeLetfWidth:"30%",
    eyeRightHeight:"100%",
    eyeRightWidth:"30%"
  },
  methods: {
    
    onReady(){
    
      //初始化蓝牙
      this.openBluetoothAdapter();
      //初始化VK
      this.init();
    },
    onHide :function(){
    
      //关闭
      this.closeBle();
    },
    onUnload :function(){
    
      this.closeBle();
    },
    // 对应案例的初始化逻辑,由统一的 behavior 触发 初始化VKstart完毕后,进行更新渲染循环
    init() {
    
      this
      // VKSession 配置
      const session = this.session = wx.createVKSession({
    
        track: {
    face: {
    mode: 1}},
        version: 'v2',
      });
      try {
    
        session.start(err => {
    
          if (err) return console.error('VK error: ', err);
          //摄像头设置为前置摄像头 1    0 为后置
          const config = session.config
          config.cameraPosition = 1;  
          session.config = config;

          console.log('VKSession.start ok,version:', session.version)
          //  VKSession EVENT resize
          session.on('resize', () => {
    
          })
          // 开启三维识别
          session.update3DMode({
    open3d: true})
          // VKSession EVENT addAnchors
          session.on('addAnchors', anchors => {
    
            console.log("addAnchor", anchors)
          })

          // VKSession EVENT updateAnchors
          session.on('updateAnchors', anchors => {
    
            var anchor = anchors[0];//第一个人脸
            //43 两个眼睛中间点     46鼻头
            var  centeracch = anchor.points[46];//两个眼睛中间点
            //72 左上眼皮  73  左下眼皮   75 右上眼皮  76 右下眼皮
            //console.log(centeracch);//鼻头
            var eyeLetfLen  = this.calen(this.calculateEye(anchor.points[72],anchor.points[73],anchor.points[52],anchor.points[55]));
            if(eyeLetfLen < 5){
    
              console.log("open led");
              //发送蓝牙数据
              this.writeBLECharacteristicValue(0x61);
            }
            var eyeRightLen = this.calen(this.calculateEye(anchor.points[75],anchor.points[76],anchor.points[58],anchor.points[61]));
            if(eyeRightLen < 5){
    
              console.log("close led");
              //发送蓝牙数据
              this.writeBLECharacteristicValue(0x62);
            }
            this.setData({
    
              originx:centeracch.x * 100 +"%",
              originy:centeracch.y * 100 +"%",
              eyeLetfHeight: eyeLetfLen + "%",
              eyeLetfWidth: (70 - (eyeLetfLen / 100 ) * 40) + "%",
              eyeRightHeight: eyeRightLen + "%",
              eyeRightWidth: (70 - (eyeRightLen / 100 ) * 40) + "%"
            })
          })
          // VKSession removeAnchors
          // 识别目标丢失时不断触发
          session.on('removeAnchors', anchors => {
    
             console.log("removeAnchors",anchors);
             this.setData({
    
              originx:"1%",
              originy:"1%"
            })
          });

          console.log('ready to initloop')
          // start 初始化完毕后,进行更新渲染循环
          this.initLoop();
        });

      } catch(e) {
    
        console.error(e);
      }
    },
    calen(eyelen){
    
        var l =  105 - eyelen;
        if(l>100){
    
          return 100;
        }else if (l < 5){
    
          return 3;
        }else{
    
          return l;
        }
    },
    calculateEye(up,dow,left,right){
    
      var ylen = this.calculateDistance(up.x,up.y,dow.x,dow.y);
      var xlen = this.calculateDistance(right.x,right.y,left.x,left.y);
      return xlen/ylen;
    },
    calculateDistance(x1, y1, x2, y2) {
      
      var dx = x2 - x1;  
      var dy = y2 - y1;  
      return Math.sqrt(dx * dx + dy * dy);  
    },
    // 限帧逻辑
    initLoop() {
    
      // 限制调用帧率,暂时去掉
      let fps = 30
      let fpsInterval = 1000 / fps
      let last = Date.now()
      const session = this.session;
      // 逐帧渲染
      const onFrame = timestamp => {
    
          try {
    
              let now = Date.now()
              const mill = now - last
              // 经过了足够的时间
              if (mill > fpsInterval) {
    
                  last = now - (mill % fpsInterval); //校正当前时间
                  session.getVKFrame(1,1);
              }
          } catch(e) {
    
              console.error(e);
          }
          session.requestAnimationFrame(onFrame)
      }
      session.requestAnimationFrame(onFrame)
  },
 
  },
})

esp32的代码是抄了其他博主的
https://blog.csdn.net/m0_45199510/article/details/131642604

代码如下

#include <Arduino.h>
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>

#define Led 2

uint8_t txValue = 0;                         //后面需要发送的值
BLEServer *pServer = NULL;                   //BLEServer指针 pServer
BLECharacteristic *pTxCharacteristic = NULL; //BLECharacteristic指针 pTxCharacteristic
bool deviceConnected = false;                //本次连接状态
bool oldDeviceConnected = false;             //上次连接状态d
// See the following for generating UUIDs: https://www.uuidgenerator.net/
#define SERVICE_UUID "2563121a-5e23-42e7-a40a-8e1c4e522e96" // UART service UUID
#define CHARACTERISTIC_UUID_RX "2563121a-5e23-42e7-a40a-8e1c4e522e96"
#define CHARACTERISTIC_UUID_TX "2563121a-5e23-42e7-a40a-8e1c4e522e96"

 //回调程序
class MyServerCallbacks : public BLEServerCallbacks
{
    
    void onConnect(BLEServer *pServer)
    {
    
        deviceConnected = true;
    };
 
    void onDisconnect(BLEServer *pServer)
    {
    
        deviceConnected = false;
    }
};
 
class MyCallbacks : public BLECharacteristicCallbacks
{
    
    void onWrite(BLECharacteristic *pCharacteristic)
    {
    
        std::string rxValue = pCharacteristic->getValue(); //接收信息
 
        if (rxValue.length() > 0)
        {
     //向串口输出收到的值
            Serial.print("RX: ");
            for (int i = 0; i < rxValue.length(); i++)
                Serial.print(rxValue[i]);
            Serial.println();
            if (rxValue[0]=='a')
              digitalWrite(Led, HIGH);
            else
              digitalWrite(Led, LOW);              
        }
    }
};
 
void setup()
{
    
    Serial.begin(115200);
 
    // 创建一个 BLE 设备
    BLEDevice::init("ESP32BLE");//在这里面是ble的名称
 
    // 创建一个 BLE 服务
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new MyServerCallbacks()); //设置回调
    BLEService *pService = pServer->createService(SERVICE_UUID);
 
    // 创建一个 BLE 特征
    pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_TX, BLECharacteristic::PROPERTY_NOTIFY);
    pTxCharacteristic->addDescriptor(new BLE2902());
    BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_UUID_RX, BLECharacteristic::PROPERTY_WRITE);
    pRxCharacteristic->setCallbacks(new MyCallbacks()); //设置回调
 
    pService->start();                  // 开始服务
    pServer->getAdvertising()->start(); // 开始广播
    Serial.println(" 等待一个客户端连接,且发送通知... ");
    pinMode(Led, OUTPUT);
}
 
void loop()
{
    
    // deviceConnected 已连接
    if (deviceConnected)
    {
    
        pTxCharacteristic->setValue(&txValue, 1); // 设置要发送的值为1
        pTxCharacteristic->notify();              // 广播
        txValue++;                                // 指针数值自加1
        delay(2000);                              // 如果有太多包要发送,蓝牙会堵塞
    }
 
    // disconnecting  断开连接
    if (!deviceConnected && oldDeviceConnected)
    {
    
        delay(500);                  // 留时间给蓝牙缓冲
        pServer->startAdvertising(); // 重新广播
        Serial.println(" 开始广播 ");
        oldDeviceConnected = deviceConnected;
    }
 
    // connecting  正在连接
    if (deviceConnected && !oldDeviceConnected)
    {
    
        // do stuff here on connecting
        oldDeviceConnected = deviceConnected;
    }
}

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/walle167/article/details/136262002

智能推荐

Unity优化——LOD技术_lod技术原理-程序员宅基地

文章浏览阅读1.4w次,点赞9次,收藏30次。什么是LODLOD是Level Of Detais 的简称,多细节层次在游戏场景中,根据摄像机与模型的距离,来决定显示哪一个模型,一般距离近的时候显示高精度多细节模型,距离远的时候显示低精度低细节模型游戏中有高模低模的存在。说白的就是离得远看不清,离得近很清楚。根据摄像机与物体距离,unity会自动切换模型。使用LOD先准备几个模型,从高模到低模。没有模型。。。低配版..._lod技术原理

javax.imageio.IIOException: Not a JPEG file: starts with 0x47 0x49-程序员宅基地

文章浏览阅读7.8k次。java处理图片时出现异常javax.imageio.IIOException: Not a JPEG file: starts with 0x47 0x49at com.sun.imageio.plugins.jpeg.JPEGImageReader.readImageHeader(Native Method)at com.sun.imageio.plugins.jpeg.JPEGI_javax.imageio.iioexception: not a jpeg file: starts with 0x52 0x49

代发外链哪家好?-程序员宅基地

文章浏览阅读343次,点赞11次,收藏6次。与其授人以鱼不如授人以渔,在这里说说如何选择好的外链商,可以先找一下你要发的这家外链商的口碑,了解其专业水平,这倒是最基本的了,说到底这些东西说得难听点都是可以伪造的,所以最重要的,是要了解外链的作用。外链可以说是网站外部优化最重要的组成部分,一个网站的外链建设对于网站网站优化是至关重要的,选择到一家好的外链商可以说成功了一半,毕竟不是谁都有外链资源。外链最重要的作用毫无疑问,就是提升网站的关键词排名,不能提升排名的外链可以说没有意义,有人就会说了,但外链的作用不是日积月累的吗?

使用Apache的ab工具进行压力测试_用apache中的ab测试接口压力中的时延是什么-程序员宅基地

文章浏览阅读442次。ab命令原理 Apache的ab命令模拟多线程并发请求,测试服务器负载压力,也可以测试nginx、lighthttp、IIS等其它Web服务器的压力。 Apache附带的ab工具(使用的PHP环境是WAMP集成环境,ab工具位于D:\wamp\bin\apache\Apache2.2.21\bin)非常容易使用。ab命令对发出负载的计算机要求很低,既不会占用很多CPU,也不会占用太多的内存,但_用apache中的ab测试接口压力中的时延是什么

falsk框架中安装flask-mysqldb报错解决方案_flask_mysqldb安装失败windows-程序员宅基地

文章浏览阅读1k次。我的是py37版本,无法直接安装flask-mysqldb。下载完成之后直接在控制台本地安装。下载mysqlclient。_flask_mysqldb安装失败windows

手把手教你启用Win10的Linux子系统(超详细)_win10自带linux子系统怎么用-程序员宅基地

文章浏览阅读10w+次,点赞143次,收藏775次。今天为大家介绍如何才能启用Windows10下的Linux子系统,废话不多说,直接看步骤:启用开发者模式打开设置 点击更新和安全 点击开发者选项 启用开发人员模式 更改系统功能使用win+X快捷键调出系统管理菜单后点击应用和功能,然后拉到底下,选择程序和功能 选中应用或关闭Windows功能 勾选适用于Linux的Windows子系统,然后确认并重启..._win10自带linux子系统怎么用

随便推点

linux详解5,2024年最新阿里珍藏版Linux运维框架体系架构手写文档-程序员宅基地

文章浏览阅读410次,点赞14次,收藏16次。三、Python定制篇 apt软件管理和远程登录自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。深知大多数Linux运维工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!因此收集整理了一份《2024年Linux运维全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

BERT系列算法解读:(RoBERTa/ALBERT/DistilBERT/Transformer/Hugging Face/NLP/预训练模型/模型蒸馏)_bert算法-程序员宅基地

文章浏览阅读758次,点赞2次,收藏6次。BERT系列算法解读(RoBERTa/ALBERT/DistilBERT/Transformer/Hugging Face/NLP/预训练模型)_bert算法

超文本标记语言_head表示超文本文件头信息的结束-程序员宅基地

文章浏览阅读6.2k次。超文本标记语言百科名片超文本标记语言,即HTML(Hypertext Markup Language),是用于描述网页文档的一种标记语言。 查看精彩图册目录基本介绍由来定义语言特点编辑发展历史超文本标记语言可扩展超文本标记语言整体结构文件头部内容文件主体内容字符集_head表示超文本文件头信息的结束

h265硬解码和软解码_h265能通过gpu解码-程序员宅基地

文章浏览阅读2k次。h.265解码库,支持GPU和CPU1.初始化PlayerSDK_Init(CallBack callBackFunc,int nType);callBackFunc 回调函数nType 视频解码方式 CPU解码或者GPU解码2.播放接口PlayerSDK_Play(char* URL, long hWnd, int nType);URL 播放地址hWnd 播放句柄nType 播放类型接口返回播放句柄号3.停止播放接口Play_h265能通过gpu解码

stable diffusion(1): webui的本地部署(windows)_sd webui torch版本-程序员宅基地

文章浏览阅读2.1k次。有一个坑一直没过去,就是如果整体环境没完全装好,但是使用我自己提前创建的python虚拟环境来启动SD启动脚本stable-diffusion-webui/webui-user.bat,期间会因为某些原因(比如没梯子东西下载不下来)启动失败,但是第二次启动时就会报没有pip模块的错误,我就只能重新创建python虚拟环境,再装一遍包,这个过程很漫长很浪费时间,所以一定跟着我的脚步,一步不要落下的走,心急吃不了热豆腐。如果没有梯子,这里很慢或者根本过不去,所以参考。三、修改url地址(梯子强可不改)_sd webui torch版本

CTFSHOW做题记录_ctfshow 龙猫-程序员宅基地

文章浏览阅读491次。CTFSHOW做题记录**CTFSHOW做题记录1**(菜菜的我要写日记啦,欢迎大佬指导)**密码学签到1给出“}wohs.ftc{galf”并且提示倒叙。**解题思路:没看提示的时候乍一看以为是栅栏密码,还想着用在线解密去做,但是定睛一看不对劲,再看题目原来就是倒叙。只需要反着来就好啦。**答案:flag{ctf.show}**今天也是元气满满的一天,好好学习。..._ctfshow 龙猫