最近开始学习Qt,结合之前学习过的caffe一起搭建了一个人脸识别登录系统的程序,新手可能有理解不到位的情况,还请大家多多指教。
我的想法是用opencv自带的人脸检测算法检测出面部,利用caffe训练好的卷积神经网络来提取特征,通过计算当前检测到的人脸与已近注册的所有用户的面部特征之间的相似度,如果最大的相似度大于一个阈值,就可以确定当前检测到的人脸对应为这个相似度最大的用户了。
###Caffe人脸识别
因为不断有新的用户加入,然而添加新用户后重新调整CNN的网络结构太费时间,所以不能用CNN去判别一个用户属于哪一类。一个训练好的人脸识别网络拥有很强大的特征提取能力(例如这里用到的VGG face),我们finetune预训练的网络时会调整最后一层的分类数目,所以最后一层的目的是为了分类,倒数第二个全连接层(或者前面的)提取到的特征通过简单的计算距离也可以达到很高的准确率,因此可以用计算相似度的方式判断类别。

载入finetune后的VGG模型

代码就不详细解释了,我用的是拿1000个人脸微调后的VGGface,效果比用直接下载来的weight文件好一点,这里可以用原始的权重文件代替。

import caffe
model_def = 'VGG_FACE_deploy.prototxt'
model_weights = 'VGG_Face_finetune_1000_iter_900.caffemodel'
# create transformer for the input called 'data'
net = caffe.Net(model_def,      # defines the structure of the modelmodel_weights,  # contains the trained weightscaffe.TEST)
transformer = caffe.io.Transformer({'data': net.blobs['data'].data.shape})
transformer.set_transpose('data', (2,0,1))  # move image channels to outermost dimension
transformer.set_mean('data', np.array([104, 117, 123]))            # subtract the dataset-mean value in each channel
transformer.set_raw_scale('data', 255)      # rescale from [0, 1] to [0, 255]
transformer.set_channel_swap('data', (2,1,0))  # swap channels from RGB to BGRxpor

计算余弦相似度

import numpy as np# 计算余弦距离
def cal_cos(A,B):num = A.dot(B.T) #若为行向量则 A * B.Tprint(B.shape)if B.ndim == 1:denom = np.linalg.norm(A) * np.linalg.norm(B)else:denom = np.linalg.norm(A) * np.linalg.norm(B, axis=1)#print(num)cos = num / denom #余弦值sim = 0.5 + 0.5 * cos #归一化return simdef cal_feature(image):#for i,img_name in enumerate(os.listdir(path)):#image = caffe.io.load_image(os.path.join(path,img_name))transformed_image = transformer.preprocess('data', image)net.blobs['data'].data[0,:,:,:] = transformed_imageoutput = net.forward()return  net.blobs['fc7'].data[0]

cal_feature函数返回fc7层的输出,也就是image通过网络提取到的特征;A的维度为[1, 4096],为需要检测的目标,B的维度为[n,4096],表示所有已注册的用户的特征,cal_cos返回n个相似度,值越大,越可能是同一个人。
###Opencv人脸检测
检测人脸位置的算法用了opencv自带的人脸检测器。

import cv2face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

PyQt界面

定义全局变量存储用户的信息,提取到的特征,我用文件的形式将这些信息保存到本地,下一次运行时提前载入。

import sys
import os
import pickle
global ALLFEATURE, NEWFEATURE, tempUsrName, ALLUSER, USRNAMEwith open('USRNAME.pickle', 'rb') as f:USRNAME = pickle.load(f)
with open('ALLUSER.pickle', 'rb') as f:ALLUSER = pickle.load(f)ALLFEATURE = np.load('usrfeature.npy')
NEWFEATURE = np.array([])
tempUsrName = {}

设计一个登录界面

用PyQt设计一个界面,实现用户注册,注册时录入照片,用户密码登录,人脸识别登录等功能。

创建一个TabWidget界面

tab1用来实现密码登录,注册,tab2用来实现人脸识别登录。

from PyQt5.QtWidgets import (QWidget, QMessageBox, QLabel, QDialog,QApplication, QPushButton, QDesktopWidget, QLineEdit, QTabWidget)
from PyQt5.QtGui import QIcon, QPixmap, QImage, QPalette, QBrush
from PyQt5.QtCore import Qt, QTimerclass TabWidget(QTabWidget):def __init__(self, parent=None):super(TabWidget, self).__init__(parent)self.setWindowTitle('Face Recognition')self.setWindowIcon(QIcon('camera.png'))self.resize(400, 260)self.center()self.mContent = passWordSign()self.mIndex = faceSign()self.addTab(self.mContent, QIcon('camera.png'), u"密码登录")self.addTab(self.mIndex, u"人脸识别")palette=QPalette()icon=QPixmap('background.jpg').scaled(400, 260)palette.setBrush(self.backgroundRole(), QBrush(icon)) #添加背景图片self.setPalette(palette)def center(self):qr = self.frameGeometry()cp = QDesktopWidget().availableGeometry().center()qr.moveCenter(cp)self.move(qr.topLeft())def closeEvent(self, event):reply = QMessageBox.question(self, 'Message',"Are you sure to quit?", QMessageBox.Yes |QMessageBox.No, QMessageBox.No)if reply == QMessageBox.Yes:event.accept()else:event.ignore() if __name__ == '__main__':app = QApplication(sys.argv)t = TabWidget()t.show()#ex = Example()
sys.exit(app.exec_())

用户注册和密码登录

分别添加两个按钮和两个文本框,文本框用于用户名和密码输入,按钮分别对应事件注册登录。addPicture用于注册时录入用户照片。

class passWordSign(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):              #self.setGeometry(0, 0, 450, 300)       self.signUpButton = QPushButton(QIcon('camera.png'), 'Sign up', self)self.signUpButton.move(300, 200)self.signInButton = QPushButton(QIcon('camera.png'), 'Sign in', self)self.signInButton.move(200, 200)self.usrNameLine = QLineEdit( self )self.usrNameLine.setPlaceholderText('User Name')self.usrNameLine.setFixedSize(200, 30)self.usrNameLine.move(100, 50)self.passWordLine = QLineEdit(self)self.passWordLine.setEchoMode(QLineEdit.Password) self.passWordLine.setPlaceholderText('Pass Word')self.passWordLine.setFixedSize(200, 30)self.passWordLine.move(100, 120)self.signInButton.clicked.connect(self.signIn)self.signUpButton.clicked.connect(self.signUp)self.show()def signIn(self):global ALLFEATURE, NEWFEATURE, tempUsrName, ALLUSER, USRNAMEif self.usrNameLine.text() not in ALLUSER:QMessageBox.information(self,"Information","用户不存在,请注册")elif ALLUSER[self.usrNameLine.text()] == self.passWordLine.text():QMessageBox.information(self,"Information","Welcome!")else:QMessageBox.information(self,"Information","密码错误!")def signUp(self):global ALLFEATURE, NEWFEATURE, tempUsrName, ALLUSER, USRNAMEif self.usrNameLine.text() in ALLUSER:QMessageBox.information(self,"Information","用户已存在!")elif len(self.passWordLine.text()) < 3:QMessageBox.information(self,"Information","密码太短!")else:tempUsrName.clear()tempUsrName[self.usrNameLine.text()] = self.passWordLine.text()self.addPicture()def addPicture(self):dialog = Dialog(parent=self)dialog.show()

录入用户人脸

点击sign up按钮后弹出一个对话框,用一个label控件显示摄像头获取的照片。首先用opencv打开摄像头,用自带的人脸检测器检测到人脸self.face后,绘制一个蓝色的框,然后resize到固定的大小(对应网络的输入)。将opencv的图片格式转换为Qlabel可以显示的格式,用Qtimer定时器每隔一段时间刷新图片。检测鼠标点击事件mousePressEvent,点击鼠标后保存当前录入的用户注册信息和对应的特征。关闭摄像头,提示注册成功。

class Dialog(QDialog):def __init__(self, parent=None):QDialog.__init__(self, parent)self.resize(240, 200)self.label = QLabel(self)  self.label.setFixedWidth(150)  self.label.setFixedHeight(150)  self.label.move(40, 20)pixMap = QPixmap("face.jpg").scaled(self.label.width(),self.label.height())  self.label.setPixmap(pixMap)self.label.show()self.timer = QTimer()self.timer.start()self.timer.setInterval(100)self.cap = cv2.VideoCapture(0)self.timer.timeout.connect(self.capPicture)def mousePressEvent(self, event):global ALLFEATURE, NEWFEATURE, tempUsrName, ALLUSER, USRNAME self.cap.release()NEWFEATURE = cal_feature(self.face).reshape([1,-1])if NEWFEATURE.size > 0:for key, value in tempUsrName.items():ALLUSER[key] = valueUSRNAME.append(key)with open('ALLUSER.pickle', 'wb') as f:pickle.dump(ALLUSER, f)with open('USRNAME.pickle', 'wb') as f:pickle.dump(USRNAME, f)print(ALLFEATURE,NEWFEATURE)ALLFEATURE = np.concatenate((ALLFEATURE, NEWFEATURE), axis=0)np.save('usrfeature.npy', ALLFEATURE)QMessageBox.information(self,"Information","Success!")def capPicture(self):if (self.cap.isOpened()):# get a frameret, img = self.cap.read()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)for (x,y,w,h) in faces:img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)roi_gray = gray[y:y+h, x:x+w]roi_color = img[y:y+h, x:x+w]self.face = cv2.resize(img[y:y+h, x:x+w],(224, 224), interpolation=cv2.INTER_CUBIC)height, width, bytesPerComponent = img.shapebytesPerLine = bytesPerComponent * width# 变换彩色空间顺序cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)# 转为QImage对象self.image = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888)self.label.setPixmap(QPixmap.fromImage(self.image).scaled(self.label.width(),self.label.height()))

人脸识别登录

登录部分与之前类似,添加一个label控件用来显示图片,两个按钮用来开始检测和选定图片。当最大的相似度大于0.9时,显示登录成功。

class faceSign(QWidget):def __init__(self):super().__init__()self.initUI()def initUI(self):self.label = QLabel(self)  self.label.setFixedWidth(260)  self.label.setFixedHeight(200)  self.label.move(20, 15)self.pixMap = QPixmap("face.jpg").scaled(self.label.width(),self.label.height())  self.label.setPixmap(self.pixMap)self.label.show()self.startButton = QPushButton('start', self)self.startButton.move(300, 50)self.capPictureButton = QPushButton('capPicture', self)self.capPictureButton.move(300, 150)self.startButton.clicked.connect(self.start)self.capPictureButton.clicked.connect(self.cap)#self.cap = cv2.VideoCapture(0)#self.ret, self.img = self.cap.read()self.timer = QTimer()self.timer.start()self.timer.setInterval(100)def start(self,event):self.cap = cv2.VideoCapture(0)self.timer.timeout.connect(self.capPicture)def cap(self,event):global ALLFEATURE, NEWFEATURE, tempUsrName, ALLUSER, USRNAMEself.cap.release()feature = cal_feature(self.face)#np.save('usrfeature.npy', ALLFEATURE)sim = cal_cos(feature,np.array(ALLFEATURE))m = np.argmax(sim)if max(sim)>0.9:print(sim, USRNAME)QMessageBox.information(self,"Information","Welcome," + USRNAME[m])else:QMessageBox.information(self,"Information","识别失败!")self.label.setPixmap(self.pixMap)def capPicture(self):if (self.cap.isOpened()):# get a frameret, img = self.cap.read()gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)for (x,y,w,h) in faces:img = cv2.rectangle(img,(x,y),(x+w,y+h),(255,0,0),2)roi_gray = gray[y:y+h, x:x+w]roi_color = img[y:y+h, x:x+w]self.face = cv2.resize(img[y:y+h, x:x+w],(224, 224), interpolation=cv2.INTER_CUBIC)height, width, bytesPerComponent = img.shapebytesPerLine = bytesPerComponent * width# 变换彩色空间顺序cv2.cvtColor(img, cv2.COLOR_BGR2RGB, img)# 转为QImage对象self.image = QImage(img.data, width, height, bytesPerLine, QImage.Format_RGB888)self.label.setPixmap(QPixmap.fromImage(self.image).scaled(self.label.width(),self.label.height()))

###效果
密码登录,输入合法的密码后点击sign in,显示欢迎。

注册界面

识别界面

登录成功

点击capPicture按钮后,开始计算相似度,大于0.9提示登录成功,并显示用户名。

###缺点和不足
程序用pyinstaller打包后,亲测可以在别的linux电脑下运行。代码和文件可以参考我的Github(没有VGG face的权重),第一次写博客,非常感谢大家的意见。总结一下不足:

  1. 初始话caffe模型很费时间,所以程序打开时要等一两秒;
  2. 用户信息用文件的形式保存并不安全,可以用mysql保存到数据库,需要时调出;
  3. 人脸位置检测可以用faster rcnn代替,再加上对齐;
  4. 识别很耗费时间,因此不能实时检测,应该可以用多线程解决。

用PyQt5+Caffe+Opencv搭建一个人脸识别登录界面相关推荐

  1. python带界面的人脸识别_PyQt5+Caffe+Opencv搭建人脸识别登录界面

    最近开始学习Qt,结合之前学习过的caffe一起搭建了一个人脸识别登录系统的程序,新手可能有理解不到位的情况,还请大家多多指教. 我的想法是用opencv自带的人脸检测算法检测出面部,利用caffe训 ...

  2. OpenCV4.5.4 DNN人脸识别模块使用介绍--如何快速搭建一个人脸识别系统

    点击下方卡片,关注"OpenCV与AI深度学习" 视觉/图像重磅干货,第一时间送达 导读 本文主要介绍OpenCV4.5.4中人脸识别模块的使用和简易人脸识别系统的搭建,供大家参考 ...

  3. 玩了一个人脸识别登录

    最近温差大,请别感冒 前言 这篇文章就没有目录了,直接从头正序开始即可. 因为突然接到了一个需求,一个xx局,内部使用的移动端项目(是我们开发的),需要添加一个人脸识别登录的需求. 内部员工使用的识别 ...

  4. 做一个人脸识别登录功能

    前天晚上散步到一个大学公寓门口,发现公寓的大门口都安装了人脸识别的门禁,就有种强烈的欲望 想要学习一下 哈哈,刚好也在做项目就想运用到这个技术-于是便有了开端. 视觉智能--人脸识别 基于阿里云的视觉 ...

  5. 使用OpenCV做一个人脸识别(Java)

    前言 当前很多博客实现人脸识别的大部分都是调用云厂家的接口,如百度,阿里云.以及我们乐橙开放平台也支持人脸识别等人工智能服务.这些都比较简单,会接开放平台,走接口请求基本上都掌握了.缺点就是有限制,收 ...

  6. 神探Sherlock如何用AI破案?教你在Excel中搭建一个人脸识别CNN网络

    作者 | Dave Smith 译者 | 刘畅 编辑 | 阿司匹林.Jane 出品 | AI科技大本营 [导读]人脸识别技术已经有了非常广泛的应用,国内大规模监控系统背后运用的技术就是人脸识别. 与大 ...

  7. opencv安装实录附十几行C++实现的一个人脸识别demo

    前言: 之前写过一篇在nano上使用opencv,nano上默认是安装了opencv的库,除了nano,我们自己电脑上也想使用opencv做一些平时图像处理验证. 本来也是看一些资料安装好的,觉得也没 ...

  8. Python+OpenCv实现AI人脸识别身份认证系统(2)——人脸数据采集、存储

    原 Python+OpenCv实现AI人脸识别身份认证系统(2)--人脸数据采集.存储 2019年07月02日 08:47:52 不脱发的程序猿 阅读数 602更多 所属专栏: 人脸识别身份认证系统设 ...

  9. 基于PYQT编写一个人脸识别软件

    转载请注明出处:http://blog.csdn.net/hongbin_xu 或 http://hongbin96.com/ 文章链接:http://blog.csdn.net/hongbin_xu ...

最新文章

  1. python学习第四课
  2. android 沉浸式导航栏
  3. Python学习笔记-DNS域名轮循业务监控
  4. 基于数据挖掘的旅游推荐APP(五):景点推荐模块
  5. 罗泾数据中心顺利投产 中国太保科技建设正式步入“两地三中心”时代
  6. 求 s=a+aa+ aaa+ aaaa +aaaaa+........的值,a是从键盘输入的,项数也为键盘输入
  7. 内存映射与DMA笔记
  8. hadoop安装教程学习
  9. ffmpeg海康SDK流接入的支持
  10. 重磅干货整理】机器学习(Machine Learning)与深度学习(Deep Learning)资料汇总
  11. 提供风声无组件上传类V2.11下载 解决图片尺寸读取问题
  12. Java小游戏中加背景音乐--有图有真相
  13. 制作一个简单的时间表
  14. 抓取Momentum图片
  15. raptor流程图赋值语句_用raptor软件画出以下程序的流程图,将结果的截图复制到答题框中...
  16. 蓝桥杯嵌入式LCD显示与LED显示问题
  17. 网上咋打印?网上打印资料文件的平台有哪些
  18. 19、控件使用之图标旋转指示仪表盘显示
  19. 免费音乐下载工具,了解一下
  20. 牛客2023年情人节比赛 (c/c++题解)

热门文章

  1. 一只仓鼠引发的热议HUAWEI nova 青春版超大内存走红
  2. 现在买笔记本电脑要注意哪些方面? 哪些比较好?
  3. 【个人记录 | UNet | 整理ing】
  4. 总结27 -- E45: ‘readonly‘ option is set (add ! to override)
  5. 除了屏下无孔全面屏,红魔7系列还有这些黑科技
  6. 曹大带我学 Go(2)—— 迷惑的 goroutine 执行顺序
  7. vue封装qq表情包和符号表情的发送
  8. 阿里云主机迁移 配置域名解析 顶级域名配置子域名
  9. 报告|中国智能音箱已入局全球市场,双重商业模式迅速扩张
  10. vue-element-admin入坑之切换中文版