电子工程师技术服务社区
公告
登录
|
注册
首页
技术问答
厂商活动
正点原子
板卡试用
资源库
下载
文章
社区首页
文章
Maix Go LBP人脸分辨
分 享
扫描二维码分享
Maix Go LBP人脸分辨
K210
人脸分辨
LBP
西栎
关注
发布时间: 2019-12-23
丨
阅读: 2780
大家好,今天这篇文章的内容是用Maix Go开发板来做一个人脸门禁的小项目,门禁系统带有人脸注册和人脸分辨的功能。在本篇文章中用到的人脸分辨算法是LBP算法,首先我们来了解一下什么是LBP。 ## LBP LBP(Local Binary Pattern, 局部二值模式)是一种用来描述图像局部纹理特征的算子,它具有旋转不变性和灰度不变性等优点,原始的LBP算子定义为在3*3的窗口内,窗口中心像素为阈值,将相邻的8个像素的灰度值与其进行比较,若周围像素值大于中心像素值,则改像素点的位置被标记为1,否则为0,这样,3*3邻域内的8个点经比较可产生8位二进制数(通常转换为十进制数即LBP码,共256种),即得到该窗口中心的LBP值,并用这个值来反映该区域的纹理信息。 ![](https://cf02.ickimg.com/bbsimages/201912/19cb9ccd9a940948213dd90e33b348c8.png) 在原始的LBP提出后,研究人员对其进行了改进和优化得到了圆形LBP算子,圆形LBP算子将3*3的邻域扩展到任意邻域,并用圆形邻域代替了正方形邻域,改进后的LBP算子允许在半径为R的圆形邻域内有任意多个像素点。从而得到了诸如半径为R的圆形区域内含有P个采样点的LBP算子。 下图为几种不同半径不同采样点的LBP算子: ![](https://cf02.ickimg.com/bbsimages/201912/c357c2202092432196936019753f3fdb.png) LBP的旋转不变模式,下图中的8中LBP模式,对应的旋转不变的LBP模式都是00001111,即LBP值为15: ![](https://cf02.ickimg.com/bbsimages/201912/75c02adf8b6c1fefe95365b2d3ba4a28.png) 上述提到的LBP算子在每一个像素点都可以得到一个LBP码,对一幅图像(记录的是每个像素点的灰度值)提取其原始的LBP算子之后,得到的原始LBP特征值依然是“一幅图片”(记录的是每个像素点的LBP值)。 ![](https://cf02.ickimg.com/bbsimages/201912/89479a82e496b81e069be05cafb3c5db.png) LBP的应用中,如纹理分类,人脸分析等,一般都不将LBP图谱作为特征向量用于分类识别,而是采用LBP特征谱的统计直方图作为特征向量用于分类识别,采用LBP来分辨人脸可以减小光照强度带来的影响。 在简单了解了LBP后我们就可以开始开发我们的人脸分辨门禁了,首先我们要分辨不同的人脸,就需要首先保存一些人脸的图片。 ## 人脸注册 在我这个简易的门禁系统里人脸注册其实就是通过按下按键来拍摄一组人脸的照片,并将这组照片保存在SD卡里面用于以后分辨是那个人的脸。那么首先我们就要需要来获取一下摄像头的图片, ```python import sensor, image, time, lcd, utime sensor.reset() #初始化摄像头 sensor.set_pixformat(sensor.GRAYSCALE) #设置摄像头输出灰度图 sensor.set_framesize(sensor.B128X128) #图片像素为128*128 sensor.set_windowing((96,112)) #设置图片大小为96*112 lcd.init() #初始化LCD ``` 上面这段程序就是对摄像头和LCD的初始化设置,因为进行LBP识别需要灰度图,所以我们通过sensor.set_pixformat()函数设置摄像头输出灰度图,并通过sensor.set_framesize()函数将图片像素设置为128*128,sensor.set_windowing()用于设置图片的大小宽和高的数值需要是8的倍数,方便进行LBP特征值的提取,最后初始化一下LCD。 我们可以通过lcd.display()来实时显示摄像头采集到的图片, ```python while 1: lcd.display(sensor.snapshot()) #屏幕显示摄像头图片 ``` 运行一下程序我们就可以看到如下显示的效果了: 接下来我们需要通过按下按键的方式来保存一组人脸的照片,在这里我是用的是Maix Go上带的一个拨轮开关, ![](https://cf02.ickimg.com/bbsimages/201912/86170c60d504b222855097a2ee259134.png) ![](https://cf02.ickimg.com/bbsimages/201912/f0f1f03b1d3ea77c7fcdd6d067fa81f6.png) 通过上图我们可以看到,拨轮开关的KEY1是连接到15脚,我们要使用这个开关,首先需要注册一下这个引脚的功能,K210支持每个外设随意映射到任意引脚,通过FPIOA功能来实现。K210有32个高速GPIO和8个通用GPIO,在这里我们将15脚作为一个高速GPIO,我们可以添加以下代码: ```python from Maix import GPIO from Maix import FPIOA from board import board_info from fpioa_manager import fm fpioa = FPIOA() fpioa.set_function(board_info.PIN15,fm.fpioa.GPIOHS0) #将PIN15脚注册为高速GPIO0 pin = fpioa.get_Pin_num(fm.fpioa.GPIOHS0) #获取当前IO注册脚 if pin == board_info.PIN15: print("set function ok") ``` 通过fpioa.set_function()我们可以将外设映射到引脚上,外设表可以去MaixPy的文档查看,出册成功后串口会返回“set_function ok”的字样。 然后我们就可以通过下面这句代码设置IO口的模式为输入 pin = GPIO(GPIO.GPIOHS0,GPIO.IN) #配置IO口模式 我们可以通过pin.value()来获取IO口的状态,这样我们就可以通过IO口的状态来检测是否有按键按下了。 然后我们当按键按下后保存10张照片, ```python #拍摄图片 s = 0 number = 0 extensions = ".jpg" photo = str(s) + str(number) + extensions if pin.value() == 0: #按下按键后拍摄10张照片 s = s + 1 number = 0 photo = str(s) + str(number) + extensions while (number < 10): #保存截取到的图片到SD卡 sensor.snapshot().save(photo) # or "example.bmp" (or others) #sensor.snapshot().save("example2.jpg") # or "example.bmp" (or others) sensor.skip_frames(time = 500) number = number + 1 name = str(number) print(photo) photo = str(s) + str(number) + extensions ``` 当按键被按下时,会通过sensor.snapshot().save()保存下摄像头采集到的图片,并以.jpg的格式保存到SD卡中,通过一个while循环我们可以依次保存10张图片,在拍摄的过程中我们可以轻微转动头部,微笑或者做其它表情来提高后续识别成功概率。在这里每保存一张图片会在串口返回图片的名称,看到第十张图片的名称返回后就说明已经拍摄完毕,也可以通过LCD或者扬声器进行提示。 这样人脸注册的部分就已经实现了。 ## 人脸分辨 接下来我们就可以进行分辨人脸的工作了,在本文的最开始说过,分辨人脸使用的是LBP法,在MaixPy里我们可以非常容易的通过img.find.lbp()来获取一张图片的LBP特征值, ```python img = sensor.snapshot() #获取当前摄像头图片 d0 = img.find_lbp((0,0,img.width(),img.height())) ``` 我们首先获取当前摄像头拍摄到的画面的LBP特征值,并将这个值保存在d0。 ```python NUM_SUBJECTS = 3 #图像库中不同人数,一共6人 NUM_SUBJECTS_IMGS = 10 #每人有2张样本图片 def min(pmin,a,s): global num if a < pmin: pmin = a num = s return pmin img = None pmin = 999999 num = 0 #人脸分辨 for s in range(1,NUM_SUBJECTS+1): dist = 0 for i in range(0,NUM_SUBJECTS_IMGS): img = image.Image("%s%s.jpg"%(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为当前最匹配的人的编号 ``` 通过上面这段程序我们可以将当前摄像头的图片与SD卡内保存的图片进行对比,通过比较LBP特征值的差异度找出最匹配的那个人。 我们用for循环嵌套来分别检测每一组的每一张图片,并使用img.find.lbp()获取SD卡中样本样本图片的LBP特征值,并保存在d1,通过image.match_descriptor()来获得d0和d1的差异度,将一个人的10张照片依次与摄像头采集到的图片进行比较,将特征差异度相加存在dist中,之后我们通过一个子程序将与SD卡内的几个人对比得到的特征差异度进行比较,得出的特征差异度最小的就是最匹配的人脸。然后串口会输出这个人的编号。这样就完成了人脸的分辨。 好了,本次教程到此就结束了,门禁的具体细节大家可以自行修改,感谢各位观看,后续我还会继续做关于这块开发板的制作和教程。
原创作品,未经权利人授权禁止转载。详情见
转载须知
。
举报文章
点赞
(
3
)
西栎
关注
评论
(1)
登录后可评论,请
登录
或
注册
Hello Pointer!!!
96
天前...
大哥,你这讲的啥玩意,也太乱了
0
回复
发布
相关文章推荐
MK-米客方德推出工业级存储卡
Beetle ESP32 C3 蓝牙数据收发
Beetle ESP32 C3 wifi联网获取实时天气信息
开箱测评Beetle ESP32-C3 (RISC-V芯片)模块
正点原子数控电源DP100测评
DP100试用评测-----开箱+初体验
Beetle ESP32 C3环境搭建
【花雕体验】16 使用Beetle ESP32 C3控制8X32位WS2812硬屏之二
X
你的打赏是对原创作者最大的认可
请选择打赏IC币的数量,一经提交无法退回 !
100IC币
500IC币
1000IC币
自定义
IC币
确定
X
提交成功 ! 谢谢您的支持
返回
我要举报该内容理由
×
广告及垃圾信息
抄袭或未经授权
其它举报理由
请输入您举报的理由(50字以内)
取消
提交