【毕设】基于openmv和arduino的人脸感应显示的代码

作品要求:

在这里插入图片描述

一、作品设计与模块选择

1.可以感应人脸

人脸识别模块选用openmv模块,因为opencv用起来相对复杂。
用官方人脸识别示例代码进行修改,得出以下代码:
获取照片:

像素点是92,112的,并且是灰度图,pgm格式,存在singtown中,然后在singtown文件夹中再新建n个名为s1,s2,s3…sn的子文件夹,其中n为整个图像库中的人数。

#快照示例#注意:你需要一个SD卡来运行这个例子。#你可以使用你的OpenMV摄像机来保存图像文件。

import sensor, image, pyb

RED_LED_PIN = 1
BLUE_LED_PIN = 3

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
sensor.set_windowing((92,112))
sensor.skip_frames(10) # Let new settings take affect.
sensor.skip_frames(time = 2000)

num = 1 #设置被拍摄者序号,第一个人的图片保存到s1文件夹,第二个人的图片保存到s2文件夹,以此类推。每次更换拍摄者时,修改num值。

n = 20 #设置每个人拍摄图片数量。

#连续拍摄n张照片,每间隔3s拍摄一次。
while(n):
    #红灯亮
    pyb.LED(RED_LED_PIN).on()
    sensor.skip_frames(time = 3000) # Give the user time to get ready.等待3s,准备一下表情。

    #红灯灭,蓝灯亮
    pyb.LED(RED_LED_PIN).off()
    pyb.LED(BLUE_LED_PIN).on()

    #保存截取到的图片到SD卡
    print(n)
    sensor.snapshot().save("singtown/s%s/%s.pgm" % (num, n) ) # or "example.bmp" (or others)

    n -= 1

    pyb.LED(BLUE_LED_PIN).off()
    print("Done! Reset the camera to see the saved image.")

其原理是根据图片和现在拍摄的相似度去判断识别人脸

LBP人脸识别代码:

NUM_SUBJECTS = 1 #图像库中不同人数,一共1人
你要识别几张脸,就改为几

import sensor, time, image, pyb  
from pyb import UART		#添加串口

sensor.reset() # Initialize the camera sensor.
sensor.set_pixformat(sensor.GRAYSCALE) # or sensor.GRAYSCALE
sensor.set_framesize(sensor.B128X128) # or sensor.QQVGA (or others)
sensor.set_windowing((92,112))
sensor.skip_frames(10) # Let new settings take affect.
sensor.skip_frames(time = 5000) #等待5s
uart = UART(3, 9600)    #设定好串口通信协议


#SUB = "s1"
NUM_SUBJECTS = 1 #图像库中不同人数,一共6人
NUM_SUBJECTS_IMGS = 20 #每人有20张样本图片



def min(pmin, a, s):
    global num
    if a<pmin:
        pmin=a
        num=s
    return pmin
while(1):

    # 拍摄当前人脸。
    img = sensor.snapshot()
    #img = image.Image("singtown/%s/1.pgm"%(SUB))
    d0 = img.find_lbp((0, 0, img.width(), img.height()))
    #d0为当前人脸的lbp特征
    img = None
    pmin = 999999
    num=0

    for s in range(1, NUM_SUBJECTS+1):
        dist = 0
        for i in range(2, NUM_SUBJECTS_IMGS+1):
            img = image.Image("singtown/s%d/%d.pgm"%(s, i))
            d1 = img.find_lbp((0, 0, img.width(), img.height()))
            #d1为第s文件夹中的第i张图片的lbp特征
            dist += image.match_descriptor(d0, d1)#计算d0 d1即样本图像与被检测人脸的特征差异度。
        print("Average dist for subject %d: %d"%(s, dist/NUM_SUBJECTS_IMGS))
        pmin = min(pmin, dist/NUM_SUBJECTS_IMGS, s)#特征差异度越小,被检测人脸与此样本更相似更匹配。
        print(pmin)
    
    print(num) # num为当前最匹配的人的编号。  
      
    if(num==1 and pmin<=5000):		#如果是第一个人,并且差异度小于5000
        print("adan")	#则打印我的名字出来
        uart.write("adan")	#则用串口打印我的名字给arduino,然后就可以用arduino进行判断了

在这里插入图片描述

实际上可以用openmv进行操作显示屏和获取温湿度,速度等等操作,因为它本身就是个STM32单片机,但是操作起来相对麻烦,所以选用了arduino进行通信控制,openmv只当一个视觉识别模块处理。

2.感应到人脸时开启显示屏显示

屏幕我选用oled显示屏,oled显示屏示例代码(简洁):

//显示中英文字符程序

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

//#define LOGO16_GLCD_HEIGHT 16 //定义显示高度
//#define LOGO16_GLCD_WIDTH  16 //定义显示宽度


#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

void setup()   {                
  Serial.begin(9600);
  // 默认情况下,我们将从3.3v线内部产生高电压! 
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //初始化I2C地址0x3D(对于128x64)
  //初始化完成
  display.clearDisplay(); //清屏
  //英文字符显示,直接用display.println或print显示字符串就行
  //println换行,print不换行
  display.setTextSize(1);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体颜色白色
  display.setCursor(0,0);             //设置字体的起始位置
  display.println("Hello, world!");   //输出字符并换行
  
  display.setTextColor(BLACK, WHITE); //设置字体黑色,字体背景白色 
  display.println(3.141592);          //输出数字并换行
  
  display.setTextSize(2);             //设置字体大小
  display.setTextColor(WHITE);        //设置字体白色
  display.print("0x");                //输出字符
  display.println(0xDEADBEEF, HEX);   //输出为ASCII编码的十六进制
  display.display();                  //显示以上
  
}

void loop() {

}

根据oled显示代码,加个串口中断,然后在串口中断执行显示,我们的效果就出来了:

#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define OLED_RESET 4
Adafruit_SSD1306 display(OLED_RESET);

#if (SSD1306_LCDHEIGHT != 64)
#error("Height incorrect, please fix Adafruit_SSD1306.h!");
#endif

volatile int flag;
String shuju;

int xs_biaozhi;       //显示标志
unsigned long  delay_data;  //延时数据


void setup() {
  Serial.begin(9600);
  // 默认情况下,我们将从3.3v线内部产生高电压!
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C); //初始化I2C地址0x3D(对于128x64)
  //初始化完成
  display.clearDisplay(); //清屏

  flag = 0;
  shuju = "0";
  Serial.begin(9600);


  display.setTextSize(3);   //字体大小
  display.setTextColor(SSD1306_WHITE);  //字体颜色
  display.setCursor(0, 0);              //字体位置
  display.println("Hello, world!");   //输出字符并换行
  display.display();                    //显示出来
  delay(1000);

  display.clearDisplay(); //清屏

  display.setTextSize(1);   //字体大小
  display.setTextColor(SSD1306_WHITE);  //字体颜色
  display.setCursor(0, 0);              //字体位置
  display.println(" ");   //输出字符并换行
  display.display();                    //显示出来
  delay(1000);

}

void loop() {
use_delay();
uart_chuli();
}

void uart_chuli()   //串口处理
{
  if (flag == 1) {
    Serial.println(shuju);
    uart_dispose();

    shuju = "";
    flag = 0;
  }
}



void use_delay()      //自定义延时函数
{
  if (xs_biaozhi == 1) //如果显示标志为1
  {
    delay_data--;   //延时数据自减

    if (delay_data == 0) //如果延时数据减到0,则清空屏幕不显示
    {
      xs_biaozhi = 0;
      
      display.clearDisplay(); //清屏

      display.setTextSize(1);   //字体大小
      display.setTextColor(SSD1306_WHITE);  //字体颜色
      display.setCursor(0, 0);              //字体位置
      display.println(" ");   //输出字符并换行
      display.display();                    //显示出来
    }
  }
}


void serialEvent() {
  while (Serial.available() > 0)
  {
    shuju = shuju + char(Serial.read());
    delay(2);
    flag = 1;
  }

}

void uart_dispose() {
  if (shuju == "adan")
  {
    display.setTextSize(2);   //字体大小
    display.setCursor(64, 32);  //字体位置
    display.println(shuju);   //输出字符并换行
    display.display();        //显示出来
    delay(100);
    xs_biaozhi = 1;           //显示标志至1
    delay_data=50000;          //延时数据为50000,不是时间,时间要靠晶振时钟频率去算,我赖得算。。。
  }
}

3.显示温度、速度等

加入DHT11模块然后在oled进行温度显示
然后加入霍尔编码器或者光电编码器就可以测小车速度了

这些都太简单了,懒得做,可以自己自行添加。

实验效果

openmv人脸识别开启屏幕

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

创客阿蛋

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值