失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > 用树莓派实现人脸识别打卡门禁系统

用树莓派实现人脸识别打卡门禁系统

时间:2024-02-06 13:24:42

相关推荐

用树莓派实现人脸识别打卡门禁系统

用树莓派实现人脸识别打卡门禁系统的构建

背景功能硬件效果源码摄像头测试代码录入信息人脸识别结论

背景

源于实习公司的人脸识别打卡系统,完成之前的项目后正好没有事情干,于是想到了这个,公司的这个打卡系统操作流程是这样的,首先用手机把你的人脸录进去,要求绕头半圈,也就是右脸,正脸,左脸,然后你再去摄像头那里,识别到你后就会帮你把门打开,顺便帮你在钉钉上打卡。

功能

我做的是简易版,实现了这个打卡系统的主要功能,能完成:信息录入,正脸识别,开门关门,名字与时间的保存。

硬件

树莓派一个,摄像头一个,显示屏一个

效果

并没有打马赛克,文件大小还被限制了,大家将就着看,

这是在电脑上的效果:

在树莓派上效果:

打卡记录:

看起来效果还是不错的

源码

源码使用的电脑上的源码,其实是差不多的,路径不一样而已

如果树莓派打不开摄像头,参考这个:

/p/5653b2b7248c

代码注释很全,不详细解释

摄像头测试代码

import cv2capCamera = cv2.VideoCapture(0)if(not capCamera.isOpened()):print("can't open this camera")exit(0)capCamera.set(cv2.CAP_PROP_FRAME_WIDTH, 320)capCamera.set(cv2.CAP_PROP_FRAME_HEIGHT, 240)while(True):# handle for the cameraret, frame = capCamera.read()if ret == True:cv2.imshow('camera',frame)else:break# handle for the video# handle for exitif (cv2.waitKey(1)) == ord('q'):breakcapCamera.release()cv2.destroyAllWindows()

录入信息

import cv2import os#configadd_name = 'xiaoming'#要录入的人名target_dir = './pic_dir/{}/'.format(add_name)if os.path.exists(target_dir) is False:os.makedirs(target_dir)def generate():face_cascade = cv2.CascadeClassifier('.\cascades\haarcascade_frontalface_default.xml')#打开摄像头camera = cv2.VideoCapture(0)forword_count = 0#正脸采集,一共20张图片while (forword_count <= 20):ret, frame = camera.read()#转化为灰度图像,用来检测人脸gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)faces = face_cascade.detectMultiScale(gray, 1.3, 5)for (x, y, w, h) in faces:#画出预测框cv2.rectangle(frame, (x, y), (x + w, y + h), (255, 0, 0), 2)f = cv2.resize(gray[y:y + h, x:x + w], (200, 200))#保存录入的图片cv2.imwrite('./pic_dir/{0}/{1}.png'.format(add_name, forword_count), f)print(forword_count)forword_count += 1#展示图片cv2.imshow("camera", frame)#一秒钟24帧if cv2.waitKey(1000 // 24) & 0xff == ord("q"):breakcamera.release()cv2.destroyAllWindows()if __name__ == "__main__":generate()

人脸识别

import osimport sysimport cv2import numpy as npimport timedef change_door(open_later_time,isOpen,new_face_position):if len(new_face_position) > 0 and isOpen == False:print('打开')isOpen = Trueif len(new_face_position) == 0 and isOpen == True:open_later_time += 1else:open_later_time = 0if open_later_time == 100:open_later_time = 0print('关闭')isOpen = Falsereturn open_later_time,isOpen,new_face_positiondef read_images(path, sz=None):#给一个地址,返回训练集c = 0X, Y = [], []names = []for dirname, dirnames, filenames in os.walk(path):#目录,子目录,子文件(只限一层目录)for subdirname in dirnames:names.append(subdirname)subject_path = os.path.join(dirname, subdirname)for filename in os.listdir(subject_path):#遍历每个名字try:if (filename == ".directory"):continuefilepath = os.path.join(subject_path, filename)im = cv2.imread(filepath, cv2.IMREAD_GRAYSCALE)if (im is None):print("image " + filepath + " is none")else:print(filepath)if (sz is not None):im = cv2.resize(im, (200, 200))X.append(np.asarray(im, dtype=np.uint8))Y.append(c)except IOError:print("I/O error({0}): {1}".format(IOError.errno, IOError.strerror))except:print("Unexpected error:", sys.exc_info()[0])raiseprint(c)c = c + 1print(Y)print(names)return [X, Y], namesdef face_rec():image_dir = './pic_dir_1'isOpen = Falseopen_later_time = 0[X, Y] , names = read_images(image_dir)Y = np.asarray(Y, dtype=np.int32)model = cv2.face.LBPHFaceRecognizer_create()model.train(np.asarray(X), np.asarray(Y))camera = cv2.VideoCapture(0)camera.set(cv2.CAP_PROP_FRAME_WIDTH, 400)camera.set(cv2.CAP_PROP_FRAME_HEIGHT, 350)face_cascade = cv2.CascadeClassifier('./cascades/haarcascade_frontalface_default.xml')re_count = 0old_face_position = {}#用来绘制预测框new_face_position = {}#用来收集新数据while (True):#print(old_face_position)#print(new_face_position)re_count += 1read, img = camera.read()faces = face_cascade.detectMultiScale(img, scaleFactor =1.3, minNeighbors=5)#print('{}的类型{}'.format(faces, type(faces)))for (x, y, w, h) in faces:gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)roi = gray[x:x + w, y:y + h]try:roi = cv2.resize(roi, (200, 200), interpolation=cv2.INTER_LINEAR)#print(roi.shape)params = model.predict(roi)#print("Label: %s, Confidence: %.2f" % (params[0], params[1]))new_face_position[names[params[0]]] = (x, y, w, h)except:continue#优化用户体验#采集三帧的人脸识别信息,将预测框画出,预测框三帧一刷新,防止预测框频繁抖动的现象if re_count == 3:re_count = 0#print(new_face_position)if len(new_face_position) > 0:for key in new_face_position.keys():(x, y, w, h) = new_face_position[key]if old_face_position.__contains__(key) is False:img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)cv2.putText(img, key, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)old_face_position[key] = (x, y, w, h)else:(o_x, o_y, o_w, o_h) = new_face_position[key]if abs((o_x-x)) <= 5 and abs((o_y-y)) <= 5:img = cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)cv2.putText(img, key, (x, y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)old_face_position[key] = (x, y, w, h)else:old_face_position = {}new_face_position = {}else:for key in old_face_position.keys():(o_x, o_y, o_w, o_h) = old_face_position[key]img = cv2.rectangle(img, (o_x, o_y), (o_x + o_w, o_y + o_h), (255, 0, 0), 2)cv2.putText(img, key, (o_x, o_y - 20), cv2.FONT_HERSHEY_SIMPLEX, 1, 255, 2)#开关门模拟和保存打卡信息#如果检测到人,并且门没有开,则打开门,并且录入信息if len(new_face_position) > 0 and isOpen == False:print('开门')#保存打卡信息t = time.strftime('%Y.%m.%d %H:%M:%S', time.localtime(time.time()))with open('jilu.txt', 'a') as file:file.writelines('{},{}\n'.format(new_face_position.keys(),t))isOpen = True#如果没有检测到人,并且门开了,计数器+1,否则计数器为0if len(new_face_position) == 0 and isOpen == True:open_later_time += 1else:open_later_time = 0#当计数器为100的时候关门if open_later_time == 100:print('关门')isOpen = Falseopen_later_time = 0cv2.imshow("camera", img)#树莓派最好将帧数设为最大,不然看起来不舒服if cv2.waitKey(1000 // 25) & 0xff == ord("q"):#if cv2.waitKey(1000 // 25) & 0xff == ord("q"):breakcv2.destroyAllWindows()if __name__ == "__main__":face_rec()

结论

在电脑上运行的很流畅,在树莓派上运行的话因树莓派而异,能明显感觉到帧数下降,不过基本功能还是能完成的

如果觉得《用树莓派实现人脸识别打卡门禁系统》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。