毕业设计:基于STM32的人脸识别快递柜系统(源码、硬件、论文)

文章目录

  • 0 前言
  • 1 主要功能
  • 2 硬件设计(原理图)
  • 3 核心软件设计
  • 4 实现效果
  • 5 最后

  • 0 前言

    🔥
    这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。

    为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天要分享的是

    🚩 毕业设计 stm32人脸识别快递柜系统(源码+硬件+论文)

    🥇学长这里给一个题目综合评分(每项满分5分)

  • 难度系数:3分
  • 工作量:3分
  • 创新点:5分
  • 🧿 项目分享:见文末!

    实物演示效果

    毕业设计 stm32人脸识别快递柜系统 – 单片机 嵌入式 物联网

    1 主要功能

    系统软件设计由柜门门禁系统程序和人脸识别系统程序两部分组成。柜门门禁部分程序主要由系统主程序、底层驱动程序以及功能模块子程序组成。人脸识别系统部分程序主要由UI界面程序、人脸检测、人脸录入数据库和保存以及人脸比对等组成。

    上位机设计方案

    (1)录入名字。当有新的成员需要录入人脸系统时,会给他录入名字,作为人脸库的文件名,且录入成功后,人脸再次出现时,摄像头录像视频会显示名字,并且打开柜门门禁,如果是陌生人则不显示名字,因为其不在人脸库中;
    (2)人脸图象录入。摄像头会打开,只需拍照新成员的各个角度的人脸即可,用于快递柜的人脸比对;
    (3)保存人脸特征。录入的人脸需要保存的人脸库中,摄像头拍到的人脸才能与人脸库比对;
    (4)远程服务器连接。连接才能与嵌入式模块联通,显示屏模块才能实时显示;
    (5)发送姓名信息。录入成功可发送该人脸的名字信息;
    (6)打开人脸门禁。点击界面中的按钮,然后系统便会跳出识别界面,然后打开摄像头,启动并运行编写好的程序,用电脑自带的摄像头进行人脸识别和检测比对,成功则发送数据到显示屏并打开继电器(柜门锁),否则显示陌生人等信息,不打开继电器(柜门锁)。

    2 硬件设计(原理图)

    3 核心软件设计

    主程序流程

    系统软硬件配置好以后,首先对系统进行初始化,确定整个系统正常运行。打开人脸门禁,当摄像头检测到人脸时,会通过WIFI上传至上位机,在上位机中再将采集到的人脸信息与本地已录入的人脸信息进行匹配,在信息匹配完成后再将结果通过WIFI上传给单片机,由单片机控制继电器模拟门禁的打开和关闭。

    上位机部分设计

    上位机需要实现的功能为与下位机建立TCP连接以接收下位机上传的人脸图像数据,再利用人脸识别技术完成识别任务。本文选用了基于Python的OpenCV开源计算机视觉库、Dlib开源机器学习库、Numpy开源数值计算库、Pillow开源图像处理库、Pandas开源数据分析库进行上位机软件程序的设计

    篇幅有限,不过多复述详细设计细节,详细的设计分享在论文中。。。

    部分关键代码

    //#include "usart.h"	 
    #include "delay.h"	   
    #include "spi.h"	 
    #include "usart.h"	 
    #include "string.h"
    #include "includes.h"
    #include "led.h"
    #include "GUI.h"
    #include "Picture.h"
    #include "dht11.h"
    #include "adc.h"
    #include "light.h"
    #include "font.h" 
    //LCD的画笔颜色和背景色	   
    u16 POINT_COLOR=0x0000;	//画笔颜色
    u16 BACK_COLOR=0xFFFF;  //背景色 
    //管理LCD重要参数
    //_lcd_dev lcddev;	   
    //写寄存器函数
    //regval:寄存器值
    void LCD_WR_REG(u16 regval)
    { 
    	SPILCD_CS_RESET;  //LCD_CS=0
      SPILCD_RS_RESET;
    	SPI_WriteByte(SPI2,regval&0x00FF);
    	SPILCD_CS_SET;  //LCD_CS=1	   		 
    }
    //写LCD数据
    //data:要写入的值
    void LCD_WR_DATA(u16 data)
    {
     	SPILCD_CS_RESET;  //LCD_CS=0
    	SPILCD_RS_SET;	
    	SPI_WriteByte(SPI2,data>>8);
    	SPI_WriteByte(SPI2,data);
    	SPILCD_CS_SET;  //LCD_CS=1		
    }
    void LCD_WR_DATA8(u8 da)   //写8位数据
    {
    	SPILCD_CS_RESET;  //LCD_CS=0
    	SPILCD_RS_SET;				    	   
    	SPI_WriteByte(SPI2,da);	
    	SPILCD_CS_SET;  //LCD_CS=1   			 
    }					   
    //写寄存器
    //LCD_Reg:寄存器地址
    //LCD_RegValue:要写入的数据
    void LCD_WR_REG_DATA(u8 LCD_Reg, u16 LCD_RegValue)
    {
    	LCD_WR_REG(LCD_Reg);
    	LCD_WR_DATA(LCD_RegValue);
    }
    //开始写GRAM
    void LCD_WriteRAM_Prepare(void)
    {
    	LCD_WR_REG(0x2c);  
    }	 
    //当mdk -O1时间优化时需要设置
    //延时i
     
    //设置光标位置
    //Xpos:横坐标
    //Ypos:纵坐标
    void LCD_SetCursor(u16 Xpos, u16 Ypos)
    {
      LCD_WR_REG(0x2a); 
    	LCD_WR_DATA8(Xpos>>8); 
    	LCD_WR_DATA8(Xpos&0XFF);	 
    	LCD_WR_REG(0x2b); 
    	LCD_WR_DATA8(Ypos>>8); 
    	LCD_WR_DATA8(Ypos&0XFF);
    } 	  
    /*************************************************
    函数名:LCD_Set_Region
    功能:设置lcd显示区域,在此区域写点数据自动换行
    入口参数:xy起点和终点
    返回值:无
    *************************************************/
    void Lcd_SetRegion(u16 x_start,u16 y_start,u16 x_end,u16 y_end)
    {		
    	LCD_WR_REG(0x2a);
    	LCD_WR_DATA8(x_start>>8);
    	LCD_WR_DATA8(0x00FF&x_start+2);;
    	LCD_WR_DATA8(x_end>>8);
    	LCD_WR_DATA8(0x00FF&x_end+2);
    	LCD_WR_REG(0x2b);
    	LCD_WR_DATA8(y_start>>8);
    	LCD_WR_DATA8(0x00FF&y_start+3);
    	LCD_WR_DATA8(y_end>>8);
    	LCD_WR_DATA8(0x00FF&y_end+3);
    	LCD_WR_REG(0x2c);
    }
    //画点
    //x,y:坐标
    //POINT_COLOR:此点的颜色
    void LCD_DrawPoint(u16 x,u16 y)
    {
    	LCD_SetCursor(x,y);		//设置光标位置 
    	LCD_WriteRAM_Prepare();	//开始写入GRAM
    	LCD_WR_DATA(POINT_COLOR); 
    } 
    /*************************************************
    函数名:LCD_Set_XY
    功能:设置lcd显示起始点
    入口参数:xy坐标
    返回值:无
    *************************************************/
    void Lcd_SetXY(u16 x,u16 y)
    {
      	Lcd_SetRegion(x,y,x,y);
    }
    /*************************************************
    函数名:LCD_DrawPoint
    功能:画一个点
    入口参数:无
    返回值:无
    *************************************************/
    void Gui_DrawPoint(u16 x,u16 y,u16 Data)
    {
    	Lcd_SetRegion(x,y,x+1,y+1);
    	LCD_WR_DATA(Data);
    
    }
    void Lcd_Reset(void)
    {
    //	LCD_RST_CLR;
    	delay_ms(100);
    //	LCD_RST_SET;
    	delay_ms(50);
    }
    //初始化lcd
    void LCD_Init(void)
    { 	 	
    	Lcd_Reset();
    	//LCD Init For 1.44Inch LCD Panel with ST7735R.
    	LCD_WR_REG(0x11);//Sleep exit 
    	delay_ms (120);
    	//ST7735R Frame Rate
    	LCD_WR_REG(0xB1); 
    	LCD_WR_DATA8(0x01); 
    	LCD_WR_DATA8(0x2C); 
    	LCD_WR_DATA8(0x2D);
    	LCD_WR_REG(0xB2); 
    	LCD_WR_DATA8(0x01); 
    	LCD_WR_DATA8(0x2C); 
    	LCD_WR_DATA8(0x2D); 
    	LCD_WR_REG(0xB3); 
    	LCD_WR_DATA8(0x01); 
    	LCD_WR_DATA8(0x2C); 
    	LCD_WR_DATA8(0x2D); 
    	LCD_WR_DATA8(0x01); 
    	LCD_WR_DATA8(0x2C); 
    	LCD_WR_DATA8(0x2D); 
    	LCD_WR_REG(0xB4); //Column inversion 
    	LCD_WR_DATA8(0x07); 
    	//ST7735R Power Sequence
    	LCD_WR_REG(0xC0); 
    	LCD_WR_DATA8(0xA2); 
    	LCD_WR_DATA8(0x02); 
    	LCD_WR_DATA8(0x84); 
    	LCD_WR_REG(0xC1); 
    	LCD_WR_DATA8(0xC5);
    	LCD_WR_REG(0xC2); 
    	LCD_WR_DATA8(0x0A); 
    	LCD_WR_DATA8(0x00);
    	LCD_WR_REG(0xC3); 
    	LCD_WR_DATA8(0x8A); 
    	LCD_WR_DATA8(0x2A); 
    	LCD_WR_REG(0xC4); 
    	LCD_WR_DATA8(0x8A); 
    	LCD_WR_DATA8(0xEE); 
    	LCD_WR_REG(0xC5); //VCOM 
    	LCD_WR_DATA8(0x0E); 
    	LCD_WR_REG(0x36); //MX, MY, RGB mode 
    	LCD_WR_DATA8(0xC8); 
    	//ST7735R Gamma Sequence
    	LCD_WR_REG(0xe0); 
    	LCD_WR_DATA8(0x0f); 
    	LCD_WR_DATA8(0x1a); 
    	LCD_WR_DATA8(0x0f); 
    	LCD_WR_DATA8(0x18); 
    	LCD_WR_DATA8(0x2f); 
    	LCD_WR_DATA8(0x28); 
    	LCD_WR_DATA8(0x20); 
    	LCD_WR_DATA8(0x22); 
    	LCD_WR_DATA8(0x1f); 
    	LCD_WR_DATA8(0x1b); 
    	LCD_WR_DATA8(0x23); 
    	LCD_WR_DATA8(0x37); 
    	LCD_WR_DATA8(0x00); 	
    	LCD_WR_DATA8(0x07); 
    	LCD_WR_DATA8(0x02); 
    	LCD_WR_DATA8(0x10); 
    
    	LCD_WR_REG(0xe1); 
    	LCD_WR_DATA8(0x0f); 
    	LCD_WR_DATA8(0x1b); 
    	LCD_WR_DATA8(0x0f); 
    	LCD_WR_DATA8(0x17); 
    	LCD_WR_DATA8(0x33); 
    	LCD_WR_DATA8(0x2c); 
    	LCD_WR_DATA8(0x29); 
    	LCD_WR_DATA8(0x2e); 
    	LCD_WR_DATA8(0x30); 
    	LCD_WR_DATA8(0x30); 
    	LCD_WR_DATA8(0x39); 
    	LCD_WR_DATA8(0x3f); 
    	LCD_WR_DATA8(0x00); 
    	LCD_WR_DATA8(0x07); 
    	LCD_WR_DATA8(0x03); 
    	LCD_WR_DATA8(0x10);  
    	
    	LCD_WR_REG(0x2a);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x7f);
    	LCD_WR_REG(0x2b);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x00);
    	LCD_WR_DATA8(0x9f);
    	LCD_WR_REG(0xF0); //Enable test command  
    	LCD_WR_DATA8(0x01); 
    	LCD_WR_REG(0xF6); //Disable ram power save mode 
    	LCD_WR_DATA8(0x00); 
    	LCD_WR_REG(0x3A); //65k mode 
    	LCD_WR_DATA8(0x05); 
    	LCD_WR_REG(0x29);//Display on
    }  
    //清屏函数
    //color:要清屏的填充色
    void Lcd_Clear(u16 Color)               
    {	
       unsigned int i,m;
       Lcd_SetRegion(0,0,X_MAX_PIXEL-1,Y_MAX_PIXEL-1);
       //Lcd_WriteIndex(0x2C);
       for(i=0;i<X_MAX_PIXEL;i++)
       { 
    		 for(m=0;m<Y_MAX_PIXEL;m++)
        {	
    	  	LCD_WR_DATA(Color);
        }
    	}		
    }
    //在指定区域内填充单个颜色
    //(sx,sy),(ex,ey):填充矩形对角坐标,区域大小为:(ex-sx+1)*(ey-sy+1)   
    //color:要填充的颜色
    void LCD_Fill(u16 sx,u16 sy,u16 ex,u16 ey,u16 color)
    {          
    u16 i,j;
    u16 xlen=0;
    xlen=ex-sx+1;	   
    for(i=sy;i<=ey;i++)
    {									   
    	LCD_SetCursor(sx,i);      				//设置光标位置 
    	LCD_WriteRAM_Prepare();     			//开始写入GRAM	  
    	for(j=0;j<xlen;j++)LCD_WR_DATA(color);	//设置光标位置 	    
    }
    }  
    //画线
    //x1,y1:起点坐标
    //x2,y2:终点坐标  
    void LCD_DrawLine(u16 x1, u16 y1, u16 x2, u16 y2)
    {
    	u16 t; 
    	int xerr=0,yerr=0,delta_x,delta_y,distance; 
    	int incx,incy,uRow,uCol; 
    	delta_x=x2-x1; //计算坐标增量 
    	delta_y=y2-y1; 
    	uRow=x1; 
    	uCol=y1; 
    	if(delta_x>0)incx=1; //设置单步方向 
    	else if(delta_x==0)incx=0;//垂直线 
    	else {incx=-1;delta_x=-delta_x;} 
    	if(delta_y>0)incy=1; 
    	else if(delta_y==0)incy=0;//水平线 
    	else{incy=-1;delta_y=-delta_y;} 
    	if( delta_x>delta_y)distance=delta_x; //选取基本增量坐标轴 
    	else distance=delta_y; 
    	for(t=0;t<=distance+1;t++ )//画线输出 
    	{  
    		LCD_DrawPoint(uRow,uCol);//画点 
    		xerr+=delta_x ; 
    		yerr+=delta_y ; 
    		if(xerr>distance) 
    		{ 
    			xerr-=distance; 
    			uRow+=incx; 
    		} 
    		if(yerr>distance) 
    		{ 
    			yerr-=distance; 
    			uCol+=incy; 
    		} 
    	}  
    }    
    //画矩形	  
    //(x1,y1),(x2,y2):矩形的对角坐标
    void LCD_DrawRectangle(u16 x1, u16 y1, u16 x2, u16 y2)
    {
    	LCD_DrawLine(x1,y1,x2,y1);
    	LCD_DrawLine(x1,y1,x1,y2);
    	LCD_DrawLine(x1,y2,x2,y2);
    	LCD_DrawLine(x2,y1,x2,y2);
    }
    //在指定位置显示一个汉字(16*16大小)
    void showhanzi16(unsigned int x,unsigned int y,unsigned char index)	
    {  
    	unsigned char i,j,k;
    	const unsigned char *temp=hanzi16;    
    	temp+=index*32;	
    	for(j=0;j<16;j++)
    	{
    		LCD_SetCursor(x,y+j);
    		LCD_WriteRAM_Prepare();	//开始写入GRAM
    		for(k=0;k<2;k++)
    		{
    			for(i=0;i<8;i++)
    			{ 		     
    			 	if((*temp&(1<<i))!=0)
    				{
    					LCD_WR_DATA(POINT_COLOR);
    				} 
    				else
    				{
    					LCD_WR_DATA(BACK_COLOR);
    				}   
    			}
    			temp++;
    		}
    	 }
    }	
    void LCD_Fast_DrawPoint(u16 x,u16 y,u16 color){
    		 //Lcd_SetRegion(x,y,x,y);
    		LCD_SetCursor(x,y);		//设置光标位置 
    	LCD_WriteRAM_Prepare();	//开始写入GRAM
    	LCD_WR_DATA(color);
    }									  
    //在指定位置显示一个字符
    //x,y:起始坐标
    //num:要显示的字符:" "--->"~"
    //size:字体大小 12/16
    //mode:叠加方式(1)还是非叠加方式(0)
    void LCD_ShowChar(u16 x,u16 y,u8 num,u8 size,u8 mode)
    {  							  
        u8 temp,t1,t;
    	u16 y0=y;
    	u16 colortemp=POINT_COLOR;      			     
    	//设置窗口		   
    	num=num-' ';//得到偏移后的值
    	if(!mode) //非叠加方式
    	{
    	    for(t=0;t<size;t++)
    	    {   
    			if(size==12)temp=asc2_1206[num][t];  //调用1206字体
    			else temp=asc2_1608[num][t];		 //调用1608字体 	                          
    	        for(t1=0;t1<8;t1++)
    			{			    
    		        if(temp&0x80)POINT_COLOR=colortemp;
    				else POINT_COLOR=BACK_COLOR;
    				LCD_DrawPoint(x,y);	
    				temp<<=1;
    				y++;
    				if(y>=Y_MAX_PIXEL){POINT_COLOR=colortemp;return;}//超区域了
    				if((y-y0)==size)
    				{
    					y=y0;
    					x++;
    					if(x>=X_MAX_PIXEL){POINT_COLOR=colortemp;return;}//超区域了
    					break;
    				}
    			}  	 
    	    }    
    	}else//叠加方式
    	{
    	    for(t=0;t<size;t++)
    	    {   
    			if(size==12)temp=asc2_1206[num][t];  //调用1206字体
    			else temp=asc2_1608[num][t];		 //调用1608字体 	                          
    	        for(t1=0;t1<8;t1++)
    			{			    
    		        if(temp&0x80)LCD_DrawPoint(x,y); 
    				temp<<=1;
    				y++;
    				if(y>=Y_MAX_PIXEL){POINT_COLOR=colortemp;return;}//超区域了
    				if((y-y0)==size)
    				{
    					y=y0;
    					x++;
    					if(x>=X_MAX_PIXEL){POINT_COLOR=colortemp;return;}//超区域了
    					break;
    				}
    			}  	 
    	    }     
    	}
    	POINT_COLOR=colortemp;	    	   	 	  
    }   
    //m^n函数
    //返回值:m^n次方.
    u32 LCD_Pow(u8 m,u8 n)
    {
    	u32 result=1;	 
    	while(n--)result*=m;    
    	return result;
    }			 
    //显示数字,高位为0,则不显示
    //x,y :起点坐标	 
    //len :数字的位数
    //size:字体大小
    //color:颜色 
    //num:数值(0~4294967295);	 
    void LCD_ShowNum(u16 x,u16 y,u32 num,u8 len,u8 size)
    {         	
    	u8 t,temp;
    	u8 enshow=0;						   
    	for(t=0;t<len;t++)
    	{
    		temp=(num/LCD_Pow(10,len-t-1))%10;
    		if(enshow==0&&t<(len-1))
    		{
    			if(temp==0)
    			{
    				LCD_ShowChar(x+(size/2)*t,y,' ',size,0);
    				continue;
    			}else enshow=1; 
    		 	 
    		}
    	 	LCD_ShowChar(x+(size/2)*t,y,temp+'0',size,0); 
    	}
    } 
    //显示字符串
    //x,y:起点坐标
    //width,height:区域大小  
    //size:字体大小
    //*p:字符串起始地址		  
    void LCD_ShowString(u16 x,u16 y,u16 width,u16 height,u8 size,u8 *p)
    {         
    	u8 x0=x;
    	width+=x;
    	height+=y;
        while((*p<='~')&&(*p>=' '))//判断是不是非法字符!
        {       
            if(x>=width){x=x0;y+=size;}
            if(y>=height)break;//退出
            LCD_ShowChar(x,y,*p,size,1);
            x+=size/2;
            p++;
        }  
    }
    char* Name_data;
    volatile uint8_t now_Count=0;
    void Load_Drow_Dialog(void)
    {
    	Lcd_Clear(WHITE);//清屏   
     	POINT_COLOR=BLUE;//设置字体为蓝色 
    	LCD_ShowString(X_MAX_PIXEL-24,0,200,16,16,"RST");//显示清屏区域
      POINT_COLOR=RED;//设置画笔蓝色 
    }
    void xianshi(void)//显示信息
    { 
    	Lcd_Clear(WHITE);//清屏   
     	POINT_COLOR=BLUE;//设置字体为蓝色 
    	BACK_COLOR=WHITE;
    // LCD_ShowString(20,20,240,12,12,"q746876041");
     showhanzi16(5,24,13);   //
     showhanzi16(25,24,14);   //
     showhanzi16(45,24,15);   //
     showhanzi16(65,24,16);   //
     showhanzi16(85,24,17);   //
     showhanzi16(105,24,18);   //
    }  
    

    4 实现效果

    实物演示效果

    毕业设计 stm32人脸识别快递柜系统 – 单片机 嵌入式 物联网

    5 最后

    包含内容

    配套详细论文

    🧿 项目分享:见文末!

    物联沃分享整理
    物联沃-IOTWORD物联网 » 毕业设计:基于STM32的人脸识别快递柜系统(源码、硬件、论文)

    发表评论