0 前言
🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。
为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是
🚩 基于stm32机器视觉的人脸识别系统
🥇学长这里给一个题目综合评分(每项满分5分)
🧿 选题指导, 项目分享:
https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md
1 简介
本系统是由stm32f103c8t6单片机最小系统电路+k210人脸识别模块实现的人脸智能门禁系统,可实现人脸录入,人脸识别等功能。
2 主要器件
- STM32F103C8T6
- K210人脸识别电路
- 语音播报电路
- 自动开关门电路(舵机驱动)
- oled屏幕显示电路
- 按键电路
- 电源电路组成
3 实现效果
整体展示  人脸识别后,舵机会旋转打开 
4 设计原理
K210实现人脸识别
人脸识别模型源码获取
去官网获取人脸识别源码和模型  注:先获取机器码(https://cn.bbs.sipeed.com/d/541-maixhub)在下载。 所需要的文件有:模型文件,程序运行的脚本文件,ide需要的bin文件。 用MaixPy连接开发板运行代码,至此就完成了基本的人脸识别功能,上述代码含有中文注释,方便大家理解代码。 根据官网提供的源码,我们可以知道人脸识别大概是怎么个流程。 根据代码来看,主要分为以下几个过程: 1、加载各种模型 2、运行人脸检测模型,在图片中找到人脸位置并框出人脸 3、将裁出的人脸图片转换成kpu接收的格式 4、运行人脸5点关键点模型,获取到左眼、右眼、鼻子、左嘴角、右嘴角的位置 5、对原始图片人脸图片进行仿射变换,变换为正脸图像,将正脸图像转为kpu格式 6、使用人脸196维特征值模型计算正脸图片的196维特征值,计算得到最终的人脸特征feature 再将得到的人脸特征与之前保存过的人脸特征进行对比得到一组分数,选择其中最大的一个分数,且该分数超过85分(可以自己设置)就认为识别出该人,并根据对应下标从names列表中得到该人的姓名。 烧录 下载好后,接下来实现的就是固件烧录,我们需要准备一个软件kflash_gui,是专门用来烧录固件的,在sipeed官网会提供一个GitHub网址,里面不仅有该软件,还有大伙所需要的例程,在例程中可以找到已经训练好的人脸模型。如下图,按照这样配置即可,连接好板子就可以烧录了。 终于,现在就可以点击ide打开了,这就是ide的界面,点左下角的连接板子,就可以愉快的跑程序了。 
5 部分核心代码
STM32代码
#include "HLK210.h"
#include "bsp_i2c_gpio.h"
#include "bsp_i2c_OLED.h"
#include "delay.h"
#include "usart3.h"
unsigned char HLK210_FaceStorageCmd[18] ={0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x03, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0xE5};
unsigned char HLK210_FaceCheckCmd[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x02, 0x0C, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x34, 0xA8};
unsigned char HLK210_FaceDelete[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x0D, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87, 0x1E};
unsigned char HLK210_LightOn[18] = {0x5A, 0x2C, 0x00, 0x00, 0x00, 0x12, 0x12, 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0xAA, 0x15};
unsigned char HLK210_RECEICV_BUFFER[HLK210_USART_REC_LEN];
_HLK210_Data HLK210_Data;
u8 HLK210_point=0;
void HLK210_Receive_Byte(u8 res)
{
HLK210_RECEICV_BUFFER[HLK210_point++] = res;
if(HLK210_point>1 && (HLK210_RECEICV_BUFFER[HLK210_point-2]==0x5a && HLK210_RECEICV_BUFFER[HLK210_point-1]==0x2c))
{
HLK210_RECEICV_BUFFER[0]=HLK210_RECEICV_BUFFER[HLK210_point-2];
HLK210_RECEICV_BUFFER[1]=HLK210_RECEICV_BUFFER[HLK210_point-1];
HLK210_point=2;
}
if(HLK210_point>=HLK210_Data.CmdDataLen)
{
HLK210_Data.isGetData = TRUE;
memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN);
memcpy(HLK210_Data.HLK210_Buffer,HLK210_RECEICV_BUFFER, HLK210_point);
}
if(HLK210_point>HLK210_USART_REC_LEN)
{
HLK210_point=HLK210_USART_REC_LEN-1;
}
}
void HLK210_ClearDate(void)
{
memset(HLK210_RECEICV_BUFFER, 0, HLK210_USART_REC_LEN);
HLK210_point=0;
HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;
memset(HLK210_Data.HLK210_Buffer, 0, HLK210_USART_REC_LEN);
HLK210_Data.isGetData = FALSE;
HLK210_Data.isParseData = FALSE;
HLK210_Data.isUsefull = FALSE;
HLK210_Data.NowMode = NORMAL;
HLK210_Data.TimeCount = 0;
}
void HLK210_Send_Cmd(u8 *cmd)
{
u8 i=0;
for(i=0;i<18;i++)
{
HLK210_SendByte(*cmd++);
}
}
void HLK210_InputFaceID(void)
{
u8 i=0;
HLK210_ClearDate();
HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;
HLK210_Data.NowMode = INPUTFACEID;
HLK210_Send_Cmd(HLK210_LightOn);
while(HLK210_Data.isGetData == FALSE);
HLK210_Data.isGetData = FALSE;
for(i=0;i<HLK210_Data.CmdDataLen;i++)
{
USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
}
HLK210_Send_Cmd(HLK210_FaceStorageCmd);
while(HLK210_Data.isGetData == FALSE);
HLK210_Data.isGetData = FALSE;
for(i=0;i<HLK210_Data.CmdDataLen;i++)
{
USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
}
HLK210_Data.CmdDataLen = HLK210_FACEANSWERLEN;
}
void HLK210_CheckFaceID(void)
{
u8 i=0;
HLK210_ClearDate();
HLK210_Data.CmdDataLen = HLK210_NORMALANSWERLEN;
HLK210_Data.NowMode = CHECKFACEID;
HLK210_Send_Cmd(HLK210_LightOn);
while(HLK210_Data.isGetData == FALSE);
HLK210_Data.isGetData = FALSE;
for(i=0;i<HLK210_Data.CmdDataLen;i++)
{
USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
}
HLK210_Send_Cmd(HLK210_FaceCheckCmd);
while(HLK210_Data.isGetData == FALSE);
HLK210_Data.isGetData = FALSE;
for(i=0;i<HLK210_Data.CmdDataLen;i++)
{
USART3_SendByte(HLK210_Data.HLK210_Buffer[i]);
}
HLK210_Data.CmdDataLen = HLK210_RECOANSWERLEN;
}
k210代码
import sensor,image,lcd
import KPU as kpu
import time
import os
from Maix import FPIOA,GPIO
from fpioa_manager import fm
import ubinascii
from machine import UART
from machine import Timer
import time
fm.register(23,fm.fpioa.UART1_TX)
fm.register(19,fm.fpioa.UART1_RX)
com = UART(UART.UART1, 115200, timeout=50, read_buf_len=4096)
tem = ''
b = []
check = 0
save = 0
switch = 0
def on_timer(timer):
global check
global save
data = []
data = com.read(2)
if data!=None:
print(data)
check = 1
if data == b'A':
save = 0
elif data == b'C':
save = 1
print(data)
tim = Timer(Timer.TIMER0, Timer.CHANNEL0, mode=Timer.MODE_ONE_SHOT, period=500,
unit=Timer.UNIT_MS,callback=on_timer, arg=on_timer,start=False)
feature_file_exists = 0
for v in os.ilistdir('/sd'):
if v[0] == 'features.txt' and v[1] == 0x8000:
feature_file_exists = 1
record_ftr=[]
record_ftrs=[]
names = ['LX', 'HLF', 'MR.3', 'Mr.4', 'Mr.5', 'Mr.6', 'Mr.7', 'Mr.8', 'Mr.9' , 'Mr.10']
reco = ''
record = []
def save_feature(feat):
with open('/sd/features.txt','a') as f:
record =ubinascii.b2a_base64(feat)
f.write(record)
st = ''
if(feature_file_exists):
print("start")
with open('/sd/features.txt','rb') as f:
s = f.readlines()
print(len(s))
for line in s:
record_ftrs.append(bytearray(ubinascii.a2b_base64(line)))
print(record_ftr,names)
print(len(record_ftr))
print("end")
task_fd = kpu.load(0x300000)
task_ld = kpu.load(0x400000)
task_fe = kpu.load(0x500000)
clock = time.clock()
lcd.init()
sensor.reset()
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)
dst_point = [(44,59),(84,59),(64,82),(47,105),(81,105)]
a = kpu.init_yolo2(task_fd, 0.5, 0.3, 5, anchor)
img_lcd=image.Image()
img_face=image.Image(size=(128,128))
a=img_face.pix_to_ai()
while(1):
check = 0
save = 0
tim.start()
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_128=face_cut.resize(128,128)
a=face_cut_128.pix_to_ai()
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()))
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]
T=image.get_affine_transform(src_point, dst_point)
a=image.warp_affine_ai(img, img_face, T)
a=img_face.ai_to_pix()
del(face_cut_128)
fmap = kpu.forward(task_fe, img_face)
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 > 80:
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 check ==1:
check = 0
record_ftr = feature
record_ftrs.append(record_ftr)
if save== 1:
save = 0
a = img.draw_string(100,100, "Stor successful", color=(0,255,0),scale=2)
print("stor successful")
save_feature(record_ftr)
break
a = img.draw_string(0,220,"face", color=(255,0,0),scale=2)
a = lcd.display(img)
🧿 选题指导, 项目分享:
https://gitee.com/dancheng-senior/project-sharing-1/blob/master/%E6%AF%95%E8%AE%BE%E6%8C%87%E5%AF%BC/README.md
6 最后
|