基于STM32F103c8t6和K210的人脸识别智能门锁(理论探讨学习,复刻难)

基于 STM32 和 K210 的人脸识别智能门锁

一、项目背景

由于我们学校的宿舍采用老式门锁在日常生活中总会出现双手不便,钥匙忘带的情况,所以就想制作一个智能门锁,同时因为正在学习人脸识别,就决定制作一个人脸识别智能门锁。

二、项目功能需求

1.可以通过按键来增删查改成员的人脸信息,在LCD屏上显示MrX的绿字表示入录成功(X表示次数)

2.在人脸识别匹配过程中,如果采集的人脸信息与人脸库匹配成功,在LCD屏上显示MrX的绿字和绿框,通过WiFi模块,让从机控制舵机开门

3.也可以通过蓝牙与手机连接,远程开门

4.在有人时才能激活人脸识别(k210持续工作发热量大)

三、元件准备

1.舵机 2.stm32f103c8t6最小系统板 3 .k210带摄像头模块的系统板 4.esp8266的WiFi模块 5.红外感应模块 6.MOS开关模块 7.蓝牙模块 8.BOM表(附在PCB处)

四、项目设计

网盘分享的文件:人脸识别智能门锁
链接: https://pan.baidu.com/s/1yLjpnFXMUTqAJlGDoeWhaQ?pwd=hrwn 提取码: hrwn 

(一)原理图设计

(二)PCB设计

(三)程序设计

由于代码过长只展示部分代码(STM32设计采用CubeMX)

1.主机(需要重定向c库函数printf到huart1)

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

	
#include <stdio.h>
#include <string.h>
#include "esp8266.h"
#include "usart.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */
extern unsigned char a_esp8266_buf;
/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t RxBuf[10];
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t rec_data;
uint8_t tx1_data[]="AT+CIPSEND=0,10\r\n";
uint8_t tx2_data[]="123\r\n";
uint8_t tx_data = 1;
uint8_t i = 0;

/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */
	
  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_USART1_UART_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  //wifi模块初始化
	HAL_UART_Receive_IT(&huart1,&rec_data,1);
	printf("AT\r\n");
	HAL_Delay(500);
	printf("AT+CWMODE=2\r\n");
	HAL_Delay(500);
	printf("AT+RST\r\n");
	HAL_Delay(3000);
	printf("AT+CWSAP=\"esp8266\",\"12345678\",6,4\r\n");
	HAL_Delay(500);
	printf("AT+CIPMUX=1\r\n");
	HAL_Delay(500);
	printf("AT+CIPSERVER=1,333\r\n");
	HAL_Delay(5000);
	
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  //接收K210的数据
  while (1)
  {
	 if(HAL_UART_Receive(&huart1, RxBuf, sizeof(RxBuf), 1000) == HAL_OK && i == 1)
	{   // 如果成功接收到数据
		// 将接收到的数据原样发送回UART1,如果在1秒内没有发送完数据,函数将返回超时错误。
		HAL_Delay(500);
	
		HAL_UART_Transmit(&huart3, tx1_data, sizeof(tx1_data), 1000);
		HAL_Delay(500);
		HAL_UART_Transmit(&huart3, tx2_data, sizeof(tx2_data), 1000);
		
	}
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */
	//人脸感应
	if(HAL_GPIO_ReadPin(GPIOA,GPIO_PIN_0)==GPIO_PIN_SET)
	{
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_RESET);
		
		i = 0;
	}	  
	else
	{
		HAL_GPIO_WritePin(GPIOA,GPIO_PIN_1,GPIO_PIN_SET);
		
		HAL_Delay(1000);
		i = 1;
	}
  }
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL2;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

2.从机(需要重定向c库函数printf到huart2)

/* USER CODE BEGIN Header */
/**
  ******************************************************************************
  * @file           : main.c
  * @brief          : Main program body
  ******************************************************************************
  * @attention
  *
  * Copyright (c) 2024 STMicroelectronics.
  * All rights reserved.
  *
  * This software is licensed under terms that can be found in the LICENSE file
  * in the root directory of this software component.
  * If no LICENSE file comes with this software, it is provided AS-IS.
  *
  ******************************************************************************
  */
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "tim.h"
#include "usart.h"
#include "gpio.h"

/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */

#include <stdio.h>
#include <string.h>
 
#include "usart.h"

/* USER CODE END Includes */

/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN PTD */

/* USER CODE END PTD */

/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */

/* USER CODE END PD */

/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */

/* USER CODE END PM */

/* Private variables ---------------------------------------------------------*/

/* USER CODE BEGIN PV */
uint8_t RxBuf[10];
uint8_t RxBuf1[1];
/* USER CODE END PV */

/* Private function prototypes -----------------------------------------------*/
void SystemClock_Config(void);
/* USER CODE BEGIN PFP */

/* USER CODE END PFP */

/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
uint8_t rec_data;
/* USER CODE END 0 */

/**
  * @brief  The application entry point.
  * @retval int
  */
int main(void)
{

  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_TIM1_Init();
  MX_USART2_UART_Init();
  MX_USART3_UART_Init();
  /* USER CODE BEGIN 2 */
  //WiFi模块初始化
    printf("AT\r\n");
	HAL_Delay(500);
	printf("AT+CWMODE=1\r\n");
	HAL_Delay(500);
	printf("AT+RST\r\n");
	HAL_Delay(3000);
	printf("AT+CIPMUX=0\r\n");
	HAL_Delay(500);
	printf("AT+CWJAP=\"esp8266\",\"12345678\"\r\n");
	HAL_Delay(5000);
	printf("AT+CIPSTART=\"TCP\",\"192.168.4.1\",333\r\n");
	HAL_Delay(500);
	
	HAL_TIM_PWM_Start(&htim1,TIM_CHANNEL_1);		//打开定时器
    
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */

    /* USER CODE BEGIN 3 */

	  if(HAL_UART_Receive(&huart2, RxBuf, sizeof(RxBuf), 1000) == HAL_OK )
		{   // 如果成功接收
			// 将接收到的数据原样发送回UART1
			HAL_Delay(500);
		    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,500);
			HAL_Delay(1000);
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,2500);
		}
		if(HAL_UART_Receive(&huart3, RxBuf1, sizeof(RxBuf1), 1000) == HAL_OK )
		{   // 如果成功接收
			// 将接收到的数据原样发送回UART1
			HAL_Delay(500);
		    __HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,500);
			HAL_Delay(1000);
			__HAL_TIM_SET_COMPARE(&htim1,TIM_CHANNEL_1,2500);
		}
	}	
  /* USER CODE END 3 */
}

/**
  * @brief System Clock Configuration
  * @retval None
  */
void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {
    Error_Handler();
  }

  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)
  {
    Error_Handler();
  }
}

/* USER CODE BEGIN 4 */

/* USER CODE END 4 */

/**
  * @brief  This function is executed in case of error occurrence.
  * @retval None
  */
void Error_Handler(void)
{
  /* USER CODE BEGIN Error_Handler_Debug */
  /* User can add his own implementation to report the HAL error return state */
  __disable_irq();
  while (1)
  {
  }
  /* USER CODE END Error_Handler_Debug */
}

#ifdef  USE_FULL_ASSERT
/**
  * @brief  Reports the name of the source file and the source line number
  *         where the assert_param error has occurred.
  * @param  file: pointer to the source file name
  * @param  line: assert_param error line source number
  * @retval None
  */
void assert_failed(uint8_t *file, uint32_t line)
{
  /* USER CODE BEGIN 6 */
  /* User can add his own implementation to report the file name and line number,
     ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
  /* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */

3.K210采用了别人的断电储存方案(固件库的烧录可以去看其他博客)

import sensor,image,lcd  # 导入相关库
from board import board_info  # 导入开发板信息
import KPU as kpu # 导入KPU神经网络处理模块
import time
import os
from Maix import FPIOA,GPIO   # 导入FPIOA和GPIO库
from fpioa_manager import fm  # 导入fpioa_manager库
import ubinascii
import time
import utime
from machine import UART


io_led_red = 13
fm.register(io_led_red, fm.fpioa.GPIO0)

led_r=GPIO(GPIO.GPIO0, GPIO.OUT)
led_r.value(0)

io_uart1_tx = 24 #串口发送引脚
io_uart1_rx = 25 #串口接收引脚

fm.register(io_uart1_tx, fm.fpioa.UART1_TX, force=True)
fm.register(io_uart1_rx, fm.fpioa.UART1_RX, force=True)

uart_A = UART(UART.UART1, 115200, timeout=1000, read_buf_len=4096)
write_str = 'get dat\r\n'
# 按键配置
fm.register(board_info.BOOT_KEY, fm.fpioa.GPIOHS0)  # 注册按键GPIO
key_gpio = GPIO(GPIO.GPIOHS0, GPIO.IN)  # 初始化按键GPIO为输入
start_processing = False  # 按键按下标志

BOUNCE_PROTECTION = 50  # 按键抖动保护时间(毫秒)
# 按键中断服务程序
def set_key_state(*_):
    global start_processing  #告诉函数start_processing是全局变量
    start_processing = True  # 设置按键按下标志为True
    utime.sleep_ms(BOUNCE_PROTECTION)# 等待以消除按键抖动

key_gpio.irq(set_key_state, GPIO.IRQ_RISING, GPIO.WAKEUP_NOT_SUPPORT)# 设置按键中断

record_ftr=[] #空列表 用于存储当前196维特征
record_ftrs=[] #空列表 用于存储按键记录下人脸特征, 可以将特征以txt等文件形式保存到sd卡后,读取到此列表,即可实现人脸断电存储。
names = ['MR.1', 'MR.2', 'MR.3', 'Mr.4', 'Mr.5', 'Mr.6', 'Mr.7', 'Mr.8', 'Mr.9' , 'Mr.10'] # 人名标签,与上面列表特征值一一对应。
reco = ''
record = []

# 将特征保存到SD卡的函数
def save_feature_to_sd(feat):
    with open('/sd/features.txt','a') as f:
        record =ubinascii.b2a_base64(feat)  #将特征编码为Base64
        f.write(record)

st = ''


feature_file_exists = 0 # 文本文件存在标志
# 检查SD卡中是否存在features.txt文件
for v in os.ilistdir('/sd'):  #进入sd卡查找
    if v[0] == 'features.txt' and v[1] == 0x8000:  #0x8000表示文件
        feature_file_exists = 1   #找到标志位变1  说明文件存在

if(feature_file_exists):
    print("start")
    with open('/sd/features.txt','rb') as f:
        s = f.readlines()#将这个文本以每一行的形式赋值为给s (因为一行代表一个人脸信息)
        print(len(s))
        for line in s:   #迭代  依次将每一行(个)人脸特征添加到record_ftrs数组
            #print(ubinascii.a2b_base64(line))
            record_ftrs.append(bytearray(ubinascii.a2b_base64(line)))# 解码Base64并存储特征(二进制)
#下面做调试用
print(record_ftrs,names)#串行终端每次重启卡查看时候存入上次保存的人脸数据
print(len(record_ftrs))#几个人脸数据
print("end")



#不管是否已经运行已经加载过,先释放掉模型文件,因为程序一次只能加载5个模型,加上这次就有6个了
kpu.deinit(kpu.load("/sd/FeatureExtraction.smodel"))
kpu.deinit(kpu.load("/sd/FaceLandmarkDetection.smodel"))
kpu.deinit(kpu.load("/sd/FaceDetection.smodel"))




# 加载SD卡中的模型
task_fd = kpu.load("/sd/FaceDetection.smodel")
task_ld = kpu.load("/sd/FaceLandmarkDetection.smodel")
task_fe = kpu.load("/sd/FeatureExtraction.smodel")

clock = time.clock()  # 初始化系统时钟,计算帧率

lcd.init() # 初始化lcd
sensor.reset() #初始化sensor 摄像头
sensor.set_pixformat(sensor.RGB565)
sensor.set_framesize(sensor.QVGA)
sensor.set_hmirror(1) #设置摄像头镜像
sensor.set_vflip(1)   #设置摄像头翻转
lcd.rotation()
sensor.run(1) #使能摄像头

anchor = (1.889, 2.5245, 2.9465, 3.94056, 3.99987, 5.3658, 5.155437, 6.92275, 6.718375, 9.01025) #anchor for face detect 用于人脸检测的Anchor
dst_point = [(44,59),(84,59),(64,82),(47,105),(81,105)] #standard face key point position 标准正脸的5关键点坐标 分别为 左眼 右眼 鼻子 左嘴角 右嘴角
a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor) #初始化人脸检测模型
img_lcd=image.Image() # 设置显示buf
img_face=image.Image(size=(128,128)) #设置 128 * 128 人脸图片buf
a=img_face.pix_to_ai() # 将图片转为kpu接受的格式
Face_recognition = 0
while(1): # 主循环
    img = sensor.snapshot()#从摄像头获取一张图片
    clock.tick() #记录时刻,用于计算帧率
    code = kpu.run_yolo2(task_fd, img)# 运行人脸检测模型
    if code:# 如果检测到人脸
        for i in code:# 迭代坐标框
            # 绘制人脸框并裁剪人脸区域
            a = img.draw_rectangle(i.rect())# 运行人脸检测模型,获取人脸坐标位置
            face_cut = img.cut(i.x(), i.y(), i.w(), i.h())# 裁剪人脸部分图片到 face_cut
            face_cut_128 = face_cut.resize(128, 128)# 将裁出的人脸图片 缩放到128 * 128像素
            a = face_cut_128.pix_to_ai()# 将猜出图片转换为kpu接受的格式
            # 人脸五点关键点检测
            fmap = kpu.forward(task_ld, face_cut_128)
            plist = fmap[:]# 获取关键点预测结果
            le = (i.x() + int(plist[0] * i.w() - 10), i.y() + int(plist[1] * i.h()))# 计算左眼位置, 这里在w方向-10 用来补偿模型转换带来的精度损失
            re = (i.x() + int(plist[2] * i.w()), i.y() + int(plist[3] * i.h()))# 计算右眼位置
            nose = (i.x() + int(plist[4] * i.w()), i.y() + int(plist[5] * i.h()))#计算鼻子位置
            lm = (i.x() + int(plist[6] * i.w()), i.y() + int(plist[7] * i.h()))#计算左嘴角位置
            rm = (i.x() + int(plist[8] * i.w()), i.y() + int(plist[9] * i.h()))#右嘴角位置
            a = img.draw_circle(le[0], le[1], 4)
            a = img.draw_circle(re[0], re[1], 4)
            a = img.draw_circle(nose[0], nose[1], 4)
            a = img.draw_circle(lm[0], lm[1], 4)
            a = img.draw_circle(rm[0], rm[1], 4)# 在相应位置处画小圆圈
            # 人脸对齐到标准位置
            src_point = [le, re, nose, lm, rm]# 图片中 5 坐标的位置
            T = image.get_affine_transform(src_point, dst_point)# 根据获得的5点坐标与标准正脸坐标获取仿射变换矩阵
            a = image.warp_affine_ai(img, img_face, T)#对原始图片人脸图片进行仿射变换,变换为正脸图像
            a = img_face.ai_to_pix() # 将正脸图像转为kpu格式
            # a = img.draw_image(img_face, (128,0))
            del (face_cut_128)  # 释放裁剪人脸部分图片
            # 计算人脸特征向量
            fmap = kpu.forward(task_fe, img_face)  # 计算正脸图片的196维特征值
            feature = kpu.face_encode(fmap[:])  #获取计算结果
            reg_flag = False
            scores = []  # 存储特征比对分数
            for j in range(len(record_ftrs)):   #迭代已存特征值
                score = kpu.face_compare(record_ftrs[j], feature) #计算当前人脸特征值与已存特征值的分数
                scores.append(score)  #添加分数总表
            max_score = 0
            index = 0
            for k in range(len(scores)):  #迭代所有比对分数,找到最大分数和索引值
                if max_score < scores[k]:
                    max_score = scores[k]
                    index = k
            if max_score > 85:# 如果最大分数大于85, 可以被认定为同一个人
                Face_recognition = 1
                a = img.draw_string(i.x(), i.y(), ("%s :%2.1f" % (
                    names[index], max_score)), color=(0, 255, 0), scale=2)
            else:
                a = img.draw_string(i.x(), i.y(), ("X :%2.1f" % (
                    max_score)), color=(255, 0, 0), scale=2)
            if start_processing:#识别到按键按下
                record_ftr = feature
                record_ftrs.append(record_ftr)#将当前特征添加到已知特征列表
                save_feature_to_sd(record_ftr) #存到SD卡
                start_processing = False
            break
    a = img.draw_string(0,220,"face", color=(255,0,0),scale=2) #显示未知 与 分数
    a = lcd.display(img) #刷屏显示
    if Face_recognition == 1:
        uart_A.write(write_str)
        Face_recognition = 0

(四)外壳设计

五、上机调试

目前该项目主要用于理论探讨学习,实际上机操作有诸多坑点,感兴趣的可以私聊我,目前的问题有功耗过高,从机与主机交互不够丝滑,舵机机械结构不适用于开门等等

成品图与操作演示

基于 STM32 和 K210 的人脸识别智能门锁

资源

通过网盘分享的文件:人脸识别智能门锁
链接: https://pan.baidu.com/s/1yLjpnFXMUTqAJlGDoeWhaQ?pwd=hrwn 提取码: hrwn 
--来自百度网盘超级会员v1的分享

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值