PythonOpenCV人脸识别(基于LBPH防照片识别警报
目录
废话
1。环境配置(jupyternotebookpython3。6。5)
2。训练集准备
3。代码思路(艹图)
4。人脸识别源码
5。参考文章
6。可能遇到的问题废话
嗯,开局说点废话,之前用stm32和esp8266改装了下宿舍门,但终究觉得没人脸识别来得舒服,所以就有了这篇文章1。环境配置(jupyternotebookpython3。6。5)
我这里用的是python3。6,如果你想搭建一个3。6的环境又不想影响原有的,可以用小黑窗(AnacondaPrompt)搭建一个虚拟环境(虚拟环境是一个独立的空间不会影响外界,也不会受外界影响,适合应对不同版本python的需求)
如何搭建虚拟环境可以看看这篇文,简单粗暴
当你搭建好虚拟环境后,第三方库的安装也要安在虚拟环境里,那么如何切换到虚拟环境里呢打开小黑窗activate虚拟环境名字就可以激活了效果如下:
看到小括号就说明已经切换到虚拟环境里了
然后就可以安装所需的第三方库了,eg。Opencv,scipy,request,dlib,安装方法如下:
1)OpenCVpipinstallihttps:pypi。tuna。tsinghua。edu。cnsimpleopencvcontribpython3。4。2。16pipinstallihttps:pypi。tuna。tsinghua。edu。cnsimpleopencvpython3。4。2。16
2)scipypipinstallscipy
3)requestpipinstallrequest
4)dlib
dlib库的安装比较麻烦,你得先找到对应版本,因为不同python版本对应不同dlib
如果你跟我一样是3。6,那装19。7就行
缺版本或找不到对应版本可以留言2。训练集准备
这个训练集捏,是借助recognizer。train得到的。yml文件,所以精度没特别高,但是拿来玩玩门锁还是够用,追求精度可以走深度学习
代码如下:
1)第一步准备照片(即你的人脸像),以序号。名称命名,例如1。xx这是为了方便切片和保存(即我们可以通过切片将每张照片的脸部特征,序号,名称一一对应)记得你照片的存放路径
2)第二步准备人脸数据集haarcascadefrontalfacealt2。xml,这个是opencv自带的用于检测人脸(注意是检测人脸不是识别人脸)这种做法我觉得有点像RIO,就是我们在一张图片中匹配人像特征不是从角落开始,而是定位人脸,然后规划一个区域,在区域内进行匹配,这样节省很多时间
3)第三步,跑代码就完事了,然后你会在你指定的文件夹里面找到yml文件,这就是你的训练集importosimportsysfromPILimportImageimportnumpyasnpimportcv2defgetImageAndLabels(path):建两个空列表后续存储数据facesSamples〔〕ids〔〕imagePaths〔os。path。join(path,f)forfinos。listdir(path)〕检测人脸facedetectorcv2。CascadeClassifier(E:jupyternotebookpracticehaarcascadeshaarcascadefrontalfacealt2。xml)打印数组imagePathsprint(路径:,imagePaths)遍历列表中的图片forimagePathinimagePaths:打开图片,灰度PILimgImage。open(imagePath)。convert(L)此时获取的是整张图片的数组imgnumpynp。array(PILimg,uint8)获取图片人脸特征,相当于riofacesfacedetector。detectMultiScale(imgnumpy)将文件名前的名字转化为ID并记录下来stridos。path。split(imagePath)〔1〕。split(。)〔0〕idint(strid)idos。path。split(imagePath)〔1〕。split(。)〔0〕预防检测到无面容照片forx,y,w,hinfaces:把ID写进ids列表中ids。append(id)把所画的方框写进facesSamples列表中facesSamples。append(imgnumpy〔y:yh,x:xw〕)打印脸部特征和idprint(id:,id)print(fs:,facesSamples)returnfacesSamples,idsifnamemain:图片路径pathE:facedormitorytrain获取图像数组和id标签数组和姓名faces,idsgetImageAndLabels(path)获取训练对象recognizercv2。face。LBPHFaceRecognizercreate()recognizer。train(faces,np。array(ids))保存文件recognizer。write(E:facedormitoryopencvtrainertrainerxx。yml)3。代码思路(艹图)
4。人脸识别源码
1)引入库importcv2importnumpyasnpimportosimporturllibimporturllib。requestimporthashlibfromscipy。spatialimportdistanceasdistfromcollectionsimportOrderedDictimportargparseimporttimeimportdlib
2)加载训练集(这里shapepredictor68facelandmarks是用于眨眼检测的)加载训练数据集文件recogizercv2。face。LBPHFaceRecognizercreate()recogizer。read(E:facedormitoryopencvtrainertrainerxx。yml)names〔〕建个空id列表warningtime0predictordlib。shapepredictor(E:facedormitoryopencvshapepredictor68facelandmarks。dat)
3)邮件函数(即识别出陌生人或可疑人用于发送抓拍照片的)importsmtplibfromPILimportImageimportemail文件名不可以和引入的库同名fromemail。mime。imageimportMIMEImage图片类型邮件fromemail。mime。textimportMIMETextMIME多用于邮件扩充协议fromemail。mime。multipartimportMIMEMultipart创建附件类型HOSTsmtp。qq。com调用的邮箱借借口SUBJECTWarning!!!设置邮件标题FROM1xxxxxxxxxqq。com发件人的邮箱需先设置开启smtp协议TO1xxxxxxxxxxxqq。com设置收件人的邮箱(可以一次发给多个人,用逗号分隔)TOxxxxxxxxxxqq。com设置收件人的邮箱(可以一次发给多个人,用逗号分隔)messageMIMEMultipart(related)邮件信息,内容为空相当于信封related表示使用内嵌资源的形式,将邮件发送给对方defsendmail(HOST,SUBJECT,FROM,TO,message):发送信息内容messagehtmlMIMEText(h1stylecolor:red;fontsize:100pxWarning!!!h1imgsrca2020imgdataimg。jpgdatasrcimgq7。q578。comef1222ed4b53b130aede08。jpg,html,utf8)message。attach(messagehtml)发送图片messageimage0MIMEText(open(E:facedormitoryunidentified0。jpg,rb)。read(),base64,utf8)messageimage0〔Contentdisposition〕attachment;filenameSuspiciouspeople。jpg设置图片在附件当中的名字messageimage1MIMEText(open(E:facedormitoryunidentified1。jpg,rb)。read(),base64,utf8)messageimage1〔Contentdisposition〕attachment;filenameSuspiciouspeople。jpg设置图片在附件当中的名字message。attach(messageimage0)添加图片文件到邮件附件中去message。attach(messageimage1)添加图片文件到邮件附件中去pathE:facedormitoryunidentifiedimagePaths〔os。path。join(path,f)forfinos。listdir(path)〕forimagePathinimagePaths:PILimgImage。open(imagePath,utf8)PILimg〔Contentdisposition〕attachment;filenameSuspiciouspeople。jpgmessage。attach(PILimg)删除缓冲图片os。remove(E:facedormitoryunidentified0。jpg)os。remove(E:facedormitoryunidentified1。jpg)发送excel附件messagexlsxMIMEText(open(emaildemo。xlsx,rb)。read(),base64,utf8)将xlsx文件作为内容发送到对方的邮箱读取excel,rb形式读取,对于MIMEText()来说默认的编码形式是base64对于二进制文件来说没有设置base64,会出现乱码messagexlsx〔ContentDisposition〕attachment;filenameemaildemochange。xlsx设置文件在附件当中的名字message。attach(messagexlsx)添加excel文件到邮件附件中去配置相关message〔From〕FROM设置邮件发件人message〔TO〕TO设置邮件收件人message〔Subject〕SUBJECT设置邮件标题emailclientsmtplib。SMTPSSL()获取传输协议emailclient。connect(HOST,465)设置发送域名,端口465resultemailclient。login(FROM,xxxxxxx)qq授权码print(登录结果,result)操作emailclient。sendmail(fromaddrFROM,toaddrsTO。split(,),msgmessage。asstring())发送邮件指令emailclient。close()关闭邮件发送客户端
写邮件函数我是借鉴这个大佬的,站在巨人肩膀上嘛,总不能什么都靠自己来
4)防照片检测(即眨眼检测)这个也可以用于疲劳检测
详见:ibugresourcesFacialpointannotationsFACIALLANDMARKS68IDXSOrderedDict(〔(mouth,(48,68)),(righteyebrow,(17,22)),(lefteyebrow,(22,27)),(righteye,(36,42)),(lefteye,(42,48)),(nose,(27,36)),(jaw,(0,17))〕)defeyeaspectratio(eye):计算距离,竖直的Adist。euclidean(eye〔1〕,eye〔5〕)Bdist。euclidean(eye〔2〕,eye〔4〕)计算距离,水平的Cdist。euclidean(eye〔0〕,eye〔3〕)ear值ear(AB)(2。0C)returneardefshapetonp(shape,dtypeint):创建682coordsnp。zeros((shape。numparts,2),dtypedtype)遍历每一个关键点得到坐标foriinrange(0,shape。numparts):coords〔i〕(shape。part(i)。x,shape。part(i)。y)returncoordsdefperventtophoto():设置判断参数EYEARTHRESH0。3EYEARCONSECFRAMES3初始化计数器COUNTER0TOTAL0检测与定位工具print(loadingfaciallandmarkpredictor。。。)detectordlib。getfrontalfacedetector()predictordlib。shapepredictor(E:facedormitoryopencvshapepredictor68facelandmarks。dat)分别取两个眼睛区域(lStart,lEnd)FACIALLANDMARKS68IDXS〔lefteye〕(rStart,rEnd)FACIALLANDMARKS68IDXS〔righteye〕读取视频print(startingvideostreamthread。。。)vscv2。VideoCapture(0)time。sleep(1。0)遍历每一帧whileTrue:预处理framevs。read()〔1〕ifframeisNone:break(h,w)frame。shape〔:2〕width1200rwidthfloat(w)dim(width,int(hr))framecv2。resize(frame,dim,interpolationcv2。INTERAREA)graycv2。cvtColor(frame,cv2。COLORBGR2GRAY)检测人脸rectsdetector(gray,0)遍历每一个检测到的人脸forrectinrects:获取坐标shapepredictor(gray,rect)shapeshapetonp(shape)分别计算ear值leftEyeshape〔lStart:lEnd〕rightEyeshape〔rStart:rEnd〕leftEAReyeaspectratio(leftEye)rightEAReyeaspectratio(rightEye)算一个平均的ear(leftEARrightEAR)2。0绘制眼睛区域leftEyeHullcv2。convexHull(leftEye)rightEyeHullcv2。convexHull(rightEye)cv2。drawContours(frame,〔leftEyeHull〕,1,(0,255,0),1)cv2。drawContours(frame,〔rightEyeHull〕,1,(0,255,0),1)检查是否满足阈值ifearEYEARTHRESH:COUNTER1else:如果连续几帧都是闭眼的,总数算一次ifCOUNTEREYEARCONSECFRAMES:TOTAL1重置COUNTER0显示cv2。putText(frame,Blinks:{}。format(TOTAL),(10,30),cv2。FONTHERSHEYSIMPLEX,0。7,(0,0,255),2)cv2。putText(frame,EAR:{:。2f}。format(ear),(300,30),cv2。FONTHERSHEYSIMPLEX,0。7,(0,0,255),2)cv2。imshow(Frame,frame)眨眼两次则判断不是照片ifTOTAL2:cv2。imwrite(rE:facedormitoryunidentified1。jpg,frame)抓拍break空格退出iford()cv2。waitKey(10):breakvs。release()cv2。destroyAllWindows()
5)人脸检测函数准备识别的图片deffacedetectdemo(img):graycv2。cvtColor(img,cv2。COLORBGR2GRAY)转换为灰度facedetectorcv2。CascadeClassifier(E:jupyternotebookpracticehaarcascadeshaarcascadefrontalfacealt2。xml)加入数据集facefacedetector。detectMultiScale(gray,1。1,5,cv2。CASCADESCALEIMAGE,(100,100),(300,300))范围在100100300300判断为脸forx,y,w,hinface:cv2。rectangle(img,(x,y),(xw,yh),color(0,0,255),thickness2)cv2。circle(img,center(xw2,yh2),radiusw2,color(0,255,0),thickness1)人脸识别ids,confidencerecogizer。predict(gray〔y:yh,x:xw〕)置信评分confidence越大越不可信ifconfidence50:globalwarningtimeglobalnumwarningtime1ifwarningtime100:cv2。imwrite(rE:facedormitoryunidentifiedstr(num)。jpg,frame)抓拍cv2。imwrite(rE:facedormitoryunidentified0。jpg,frame)抓拍time。sleep(0。1)sendmail(HOSTHOST,SUBJECTSUBJECT,FROMFROM,TOTO,messagemessage)print(ddddddddddd)num1warningtime0cv2。putText(img,unidentified,(x10,y10),cv2。FONTHERSHEYSIMPLEX,0。75,(0,255,0),1)else:cv2。putText(img,str(names〔ids1〕),(x10,y10),cv2。FONTHERSHEYSIMPLEX,0。75,(0,255,0),1)cv2。imshow(result,img)取名函数,切片取名,即照片名为1。cj。jpg,取名后就为cjdefname():相册路径pathE:facedormitorytrain循环读图imagePaths〔os。path。join(path,f)forfinos。listdir(path)〕forimagePathinimagePaths:切名字namestr(os。path。split(imagePath)〔1〕。split(。,2)〔1〕)names。append(name)
6)主函数防照片识别perventtophoto()打开摄像头,0是本地默认,1是外用,我把本地关了把外用开着所以直接0capcv2。VideoCapture(0)name()whileTrue:flag,framecap。read()ifnotflag:breakfacedetectdemo(frame)空格退出iford()cv2。waitKey(10):breakcv2。destroyAllWindows()cap。release()5。参考文章
感谢大佬1
感谢大佬2
感谢大佬36。可能遇到的问题
1。如果你搭建了虚拟环境且里面安装了opencv,但是再引用的时候报错没装库,看看有没有将虚拟环境导入kernel
2。如果你发现我的逻辑有问题,相信你自己,错的肯定是我,请务必怼我,毕竟有探讨才有完善,我也是个小菜鸡
3。如果出现NomodulenamedXXX,说明安装差库了,请跑到虚拟环境里去安装,虚拟环境是独立的,你之前安装了什么都跟虚拟环境无关