日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > windows >内容正文

windows

基于树莓派的人脸识别门禁系统

發布時間:2023/12/10 windows 59 豆豆
生活随笔 收集整理的這篇文章主要介紹了 基于树莓派的人脸识别门禁系统 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、樹莓派Opencv以及擴展模塊的安裝

1、概述:本次在樹莓派上安裝Opencv及其擴展模塊,考慮到樹莓派的SD卡容量和內存的限制,不采用直接pip安裝方法,而采用編譯Opencv源碼的方式進行安裝。
2、遇到的問題及解決方法

遇到的問題解決方法
缺少”cuda.hpp”將/home/pi/opencv_contrib3.4.1/modules/xfeatures2d/include/opencv2下的xfeatures2d文件夾復制到home/pi/opencv-3.4.1/modules/stitching/include/opencv2下
缺少”bosstdesc_bgm.i”下載對應的文件到opencv_contrib/modules/xfeatures2d/src下
運行至99%時樹莓派卡死原本采用make -j4進行源碼編譯加速,但是多次嘗試仍然卡死,之后采用make解決了問題,可能原因是make -j4所需的交換空間太大導致卡死。

3、運行結果

導入opencv庫沒有問題,說明安裝成功。

二、樹莓派人臉檢測

1、概述:本次在樹莓派上檢測人臉用Opencv自帶的Haar特征分類器。
2、代碼編寫:
將.xml文件拷貝到mu_code文件夾下,在mu_code下編寫代碼,則工程的根目錄默認在mu_code。

import cv2 cap=cv2.VideoCapture(0) cascadePath = "/home/pi/opencv-3.4.3/data/haarcascades/haarcascade_frontalface_default.xml" faceCascade = cv2.CascadeClassifier(cascadePath) while (True):ret, img = cap.read()# 灰度化處理gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)faces = faceCascade.detectMultiScale(gray, 1.3, 5)if len(faces)!=0:x = faces[0][0]y = faces[0][1]w = faces[0][2]h = faces[0][3]cv2.rectangle(img, (x, y), (x + w, y + h), (255, 0, 0), 2)cv2.imshow("fle",img)cv2.waitKey(10)

3、運行結果:

由圖中可以看出可以正確檢測出人臉。

三、樹莓派人臉識別

1、概述:
本次在樹莓派上進行人臉識別采用OpenCV人臉識別類LBPHFaceRecognizer。
2、代碼編寫:

import cv2 from PIL import Image import numpy as np imagePath="face.png" img_face=cv2.imread(imagePath,0) cv2.imshow("fle",img_face) cv2.waitKey(0) recognizer = cv2.face.LBPHFaceRecognizer_create() PIL_img = Image.open(imagePath).convert('L') img_numpy = np.array(PIL_img, 'uint8') faces=[] ids=[] faces.append(img_numpy) ids.append(2) recognizer.train(faces, np.array(ids)) id, confidence = recognizer.predict(img_face) print("id=",id) print("confidence=",confidence)

3、運行結果:


人臉圖片用于訓練,用于訓練的id是2,這里只是為了檢測代碼的正確性,所以依然用這張圖片是做識別,識別的結果是id=2,confidence≈9.8。Id號識別正確,confidence接近于0,說明識別率很高。

四、樹莓派利用雙色LED模擬開關門動作

1、概述:
設計一個雙色LED類,該類應該能夠向外提供兩個方法,分別設置紅燈和綠燈的PWM。
這里在主函數調用是都是設置為滿PWM。
2、接線

樹莓派3mm雙色LED模塊
GND負極(-)
P17紅色燈正極(中間引腳)
P18綠色燈正極

3、代碼編寫

import RPi.GPIO as GPIO import time class Double_LED_Class:def __init__(self): # double_led 初始化工作makerobo_pins = (11, 12) # PIN管腳字典GPIO.setmode(GPIO.BOARD) # 采用實際的物理管腳給GPIO口GPIO.setwarnings(False) # 去除GPIO口警告GPIO.setup(makerobo_pins, GPIO.OUT) # 設置Pin模式為輸出模式GPIO.output(makerobo_pins, GPIO.LOW) # 設置Pin管腳為低電平(0V)關閉LEDself.p_R = GPIO.PWM(makerobo_pins[0], 2000) # 設置頻率為2KHzself.p_G = GPIO.PWM(makerobo_pins[1], 2000) # 設置頻率為2KHz# 初始化占空比為0(led關閉)self.p_R.start(0)self.p_G.start(0)def makerobo_pwm_map(self,x, in_min, in_max, out_min, out_max):return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_mindef makerobo_set_red_Color(self,col): # 例如:col = 0x1122# 把0-255的范圍同比例縮小到0-100之間R_val = self.makerobo_pwm_map(col, 0, 255, 0, 100)self.p_R.ChangeDutyCycle(R_val) # 改變占空比def makerobo_set_green_Color(self,col): # 例如:col = 0x1122# 把0-255的范圍同比例縮小到0-100之間G_val = self.makerobo_pwm_map(col, 0, 255, 0, 100)self.p_G.ChangeDutyCycle(G_val) # 改變占空比# 釋放資源def makerobo_destroy(self):self.p_G.stop()self.p_R.stop()GPIO.output(self.makerobo_pins, GPIO.LOW) # 關閉所有LEDGPIO.cleanup() # 釋放資源# 測試用例 if __name__ == "__main__":Hardware_double_led=Double_LED_Class()Hardware_double_led.makerobo_set_red_Color(200)time.sleep(3)#顯示紅燈3s后顯示綠燈Hardware_double_led.makerobo_set_red_Color(0)Hardware_double_led.makerobo_set_green_Color(200)

4、運行結果

五、樹莓派門禁系統界面設計與整體邏輯代碼整合

1、概述:
樹莓派門禁系統總共包括4個界面設計,分別是人臉識別開門界面、管理員登錄界面、人臉錄入界面、人臉數據庫展示界面。這四個界面都用PyQt5進行設計,先在Window上用Qt Designer搭建界面,用Python編寫邏輯關系,最后移植到樹莓派上,樹莓派上只需要安裝PyQt庫即可運行程序。
下面為四個界面的展示圖:




界面控件的邏輯關系如下圖:

2、代碼編寫:
代碼思路:

創建了四個界面類,分別繼承于用Qt Designer創建 的四個界面類,這樣做是為了能夠在更改界面的時候不會改變邏輯部分代碼。另外創建了一個數據庫操作類,主要是為了能夠查詢,讀寫數據庫,這里采用的是SQlite數據庫。
Main文件:

######################################### #Author:郭先達 #date:2021.12.22 #######################################33 import sys import cv2 import threading from PyQt5.QtCore import QBasicTimer from PyQt5.QtCore import * from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QLabel, QLineEdit, QGridLayout, QMessageBox, QGroupBox from PyQt5 import QtWidgets from PyQt5 import QtCore, QtGui, QtWidgets from PyQt5.QtWidgets import QWidget, QLabel, QApplication from PIL import Image import numpy as np from PyQt5.QtWidgets import * from PyQt5.QtCore import * from PyQt5.QtGui import QPalette, QBrush, QPixmap from PyQt5.QtSql import * import time from double_led import Double_LED_Class import osfrom MainWindow import Ui_Dialog as Ui_Dialog_MainWindow from Admin_enter import Ui_Dialog as Ui_Dialog_Admin_enter from Face_rec import Ui_Dialog as Ui_Dialog_Face_rec from SQliteWindow import Ui_Dialog as Ui_Dialog_SQliteWindow# 導入OpenCV自帶的數據集,定義多個是因為在后面有多次調用,用一個的話會報錯 cascadePath = "haarcascade_frontalface_default.xml" faceCascade1 = cv2.CascadeClassifier(cascadePath) faceCascade2= cv2.CascadeClassifier(cascadePath) faceCascade3 = cv2.CascadeClassifier(cascadePath) faceCascade4=cv2.CascadeClassifier(cascadePath)#人臉識別開門界面 class Fle_MainWindow(QDialog,Ui_Dialog_MainWindow):def __init__(self):super(Fle_MainWindow,self).__init__()self.setupUi(self)# 創建定時器,定時器用來定時拍照self.timer_camera = QtCore.QTimer()self.user = []#進入人臉識別開門界面之前先把所有數據訓練一遍,以滿足新數據的錄入self.recognizer = cv2.face.LBPHFaceRecognizer_create()faces, ids = self.getImagesAndLabels("./Face_data")#拍攝的照片放在這個文件夾下self.recognizer.train(faces, np.array(ids))#開始訓練self.font = cv2.FONT_HERSHEY_SIMPLEX#攝像頭初始化self.camera_init()#綁定函數show_cameraself.timer_camera.timeout.connect(self.show_camera)#30ms拍一次照片self.timer_camera.start(30)# 點擊管理員按鈕事件self.pushButton_administrators.clicked.connect(self.slot_btn_admin)#新建一個雙色LED類self.Hardware_double_led=Double_LED_Class()# 函數獲取圖像和標簽數據def getImagesAndLabels(self,path):imagePaths = [os.path.join(path, f) for f in os.listdir(path)]faceSamples = []#人臉數據ids = []#人臉對應的id標簽for imagePath in imagePaths:# 轉換為灰度PIL_img = Image.open(imagePath).convert('L')img_numpy = np.array(PIL_img, 'uint8')#print(imagePath),打印出具體信息,怎么分割就怎么設置序號id = int(imagePath.split("/")[2].split(".")[1])faces = faceCascade3.detectMultiScale(img_numpy)for (x, y, w, h) in faces:faceSamples.append(img_numpy[y:y + h, x:x + w])ids.append(id)print(ids)return faceSamples, idsdef camera_init(self):# 打開設置攝像頭對象self.cap = cv2.VideoCapture(0)self.__flag_work = 0self.x = 0self.count = 0#這里的minW和minH用于限制人臉的最小寬高,防止誤測self.minW = 0.2 * self.cap.get(3)#視頻流的幀寬度self.minH = 0.2 * self.cap.get(4)#視頻流的幀高度def show_camera(self):flag, self.image = self.cap.read()# 將圖片變化成灰度圖gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)# 探測圖片中的人臉faces = faceCascade1.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(int(self.minW), int(self.minH)),)# 判斷是否檢測到人臉,檢測到設置為綠燈,沒檢測到設置為紅燈if len(faces)!=0:#下面這個操作是為了能夠只檢測到一張臉,檢測面積最大的那個臉WxH_max=0 #人臉矩形的面積WxH_max_face=faces[0]for i in faces:if(i[2]*i[3]>WxH_max):WxH_max=i[2]*i[3]WxH_max_face=i# 圍繞臉的框x=WxH_max_face[0]y = WxH_max_face[1]w = WxH_max_face[2]h = WxH_max_face[3]cv2.rectangle(self.image, (x, y), (x + w, y + h), (0, 255, 0), 2)#用recognizer進行識別判斷id, confidence = self.recognizer.predict(gray[y:y + h, x:x + w])# 對置信度進行判斷,這里設定為70if (confidence < 70):confidence = " {0}%".format(round(100 - confidence))for i in range(0,mysqlite.get_rows()):if mysqlite.find_data(i,0)==id:self.label_ID.setText(str(mysqlite.find_data(i,1)))self.label_name.setText(str(mysqlite.find_data(i,2)))self.Hardware_double_led.makerobo_set_red_Color(0)self.Hardware_double_led.makerobo_set_green_Color(100)else:confidence = " {0}%".format(round(100 - confidence))self.label_ID.setText("不認識")self.label_name.setText("不認識")self.Hardware_double_led.makerobo_set_red_Color(100)self.Hardware_double_led.makerobo_set_green_Color(0)# 給圖片添加文本 圖片矩陣, 添加文本名稱, 設置文本顯示位置,# 字體樣式, 字體大小, 字體顏色, 字體粗細cv2.putText(self.image, str(id), (x + 5, y - 5), self.font, 1, (255, 255, 255), 2)cv2.putText(self.image, str(confidence), (x + 5, y + h - 5), self.font, 1, (255, 255, 0), 1)else:self.Hardware_double_led.makerobo_set_red_Color(0)self.Hardware_double_led.makerobo_set_green_Color(0)# 將視頻顯示在了label上show = cv2.resize(self.image, (640, 480))show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)self.lab_face.setPixmap(QtGui.QPixmap.fromImage(showImage))# 點點擊管理員按鈕事件def slot_btn_admin(self):#應該在釋放攝像頭之前先關閉定時器self.timer_camera.stop()self.cap.release()self.logon = Fle_Admin_enter()self.logon.show()self.hide()#其他界面不用雙色LED模擬開關門,把燈滅掉self.Hardware_double_led.makerobo_set_red_Color(0)self.Hardware_double_led.makerobo_set_green_Color(0)# 管理員登錄界面 class Fle_Admin_enter(QDialog,Ui_Dialog_Admin_enter):def __init__(self):super(Fle_Admin_enter, self).__init__()self.setupUi(self)#將輸入信息初始化為空self.lineEdit_admin_ID.setText("")self.lineEdit_admin_key.setText("")#設置密碼為隱藏方式顯示self.lineEdit_admin_key.setEchoMode(QLineEdit.Password)# lineEdit改變事件self.lineEdit_admin_ID.textEdited[str].connect(self.changeEdit_ID)self.lineEdit_admin_key.textEdited[str].connect(self.changeEdit_key)# 點擊返回按鈕事件self.pushButton_admin_back.clicked.connect(self.slot_btn_back)# 點擊登錄按鈕事件self.pushButton_admin_enter.clicked.connect(self.slot_btn_logon)# 點擊Edit_ID事件def changeEdit_ID(self):Edit_ID = self.lineEdit_admin_ID.text()print("Edit_ID=",Edit_ID)# 點擊Edit_key事件def changeEdit_key(self):Edit_key = self.lineEdit_admin_key.text()print("Edit_ID=",Edit_key)# 點擊返回按鈕事件def slot_btn_back(self):self.menu = Fle_MainWindow()self.menu.show()self.hide()# 點擊登錄按鈕事件def slot_btn_logon(self):# 判斷賬號和密碼是否輸入正確print(self.lineEdit_admin_ID.text)print(self.lineEdit_admin_key.text)#這里設置管理員的賬號和密碼,這里都設置為1if self.lineEdit_admin_ID.text() == "1" and self.lineEdit_admin_key.text() == "1":self.manager_face = Fle_Face_rec()self.manager_face.show()self.hide()#print("enter Ui_manager_face")else:QMessageBox.warning(self, "提示", "賬號或密碼錯誤!", QMessageBox.Close)#人臉錄入界面 class Fle_Face_rec(QDialog,Ui_Dialog_Face_rec):def __init__(self):super(Fle_Face_rec, self).__init__()self.setupUi(self)# 初始化為空self.lineEdit_ID.setText("")self.lineEdit_name.setText("")# 初始化進度條定時器self.timer = QBasicTimer()self.step = 0# 創建定時器self.timer_camera = QtCore.QTimer()# 初始化攝像頭數據self.camera_init()# 定時器函數,用來顯示人臉檢測結果,并不錄入數據self.timer_camera.timeout.connect(self.show_camera)self.timer_camera.start(30)self.pushButton_begin_rec.clicked.connect(self.slot_btn_enter)self.pushButton_back.clicked.connect(self.slot_btn_back)self.pushButton_show_sqlite.clicked.connect(self.show_sqlitedata)# 初始化攝像頭數據def camera_init(self):self.cap = cv2.VideoCapture(0)self.__flag_work = 0self.x =0self.count = 0#設置分辨率為640*480self.cap.set(4,640)self.cap.set(3,480)# 點擊返回按鍵返回上一界面def slot_btn_back(self):self.timer_camera.stop()self.cap.release()self.logon = Fle_MainWindow()self.logon.show()self.hide()def show_camera(self):flag, self.image = self.cap.read()gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)faceCascade2 = cv2.CascadeClassifier(cascadePath);faces = faceCascade2.detectMultiScale(gray,scaleFactor=1.2,minNeighbors=5,minSize=(200, 200))if len(faces)!=0:WxH_max = 0WxH_max_face = faces[0]for i in faces:if (i[2] * i[3] > WxH_max):WxH_max = i[2] * i[3]WxH_max_face = i# 圍繞臉的框x = WxH_max_face[0]y = WxH_max_face[1]w = WxH_max_face[2]h = WxH_max_face[3]cv2.rectangle(self.image, (x, y), (x + w, y + h), (255, 0, 0), 2)roi_gray = gray[y:y + h, x:x + w]roi_color = self.image[y:y + h, x:x + w]# 將視頻顯示在了label上show = cv2.resize(self.image, (640, 480))show = cv2.cvtColor(show, cv2.COLOR_BGR2RGB)showImage = QtGui.QImage(show.data, show.shape[1], show.shape[0], QtGui.QImage.Format_RGB888)self.label_face.setPixmap(QtGui.QPixmap.fromImage(showImage))# 點擊按鈕開啟人臉錄入線程def slot_btn_enter(self):self.count = 0# 創建線程并開啟self.thread = threading.Thread(target=self.thread_pic)self.thread.start()# 開啟進度條定時器self.timer.start(100, self)# 加載進度條def timerEvent(self, e):self.progressBar.setValue(self.count)# 錄入人臉線程def thread_pic(self):tip="正在錄入"+str(self.lineEdit_ID.text())+str(self.lineEdit_name.text())+"的人臉!!"print(tip)# 創建目錄,將獲取的人臉照片放入指定的文件夾self.file = "./Face_data"file_ID=str(self.lineEdit_ID.text())while (True):# 灰度化處理gray = cv2.cvtColor(self.image, cv2.COLOR_BGR2GRAY)faces = faceCascade4.detectMultiScale(gray, 1.3, 5)if len(faces)!=0:WxH_max = 0WxH_max_face = faces[0]for i in faces:if (i[2] * i[3] > WxH_max):WxH_max = i[2] * i[3]WxH_max_face = i# 圍繞臉的框x = WxH_max_face[0]y = WxH_max_face[1]w = WxH_max_face[2]h = WxH_max_face[3]self.count += 1# 將捕獲的圖像命名為User.0.1.png,其中0是id號print(self.file + "/User." + file_ID + '.' + str(self.count) + ".png")bool = cv2.imwrite(self.file + "/User." + file_ID + '.' + str(self.count) + ".png",gray[y:y + h, x:x + w])# 取100張人臉樣本,停止錄像if self.count >= 100:print("人臉數據采集已完成!")break#將數據存入數據庫mysqlite.add_row(self.lineEdit_ID.text(),self.lineEdit_xuehao.text(),str(self.lineEdit_name.text()))def show_sqlitedata(self):self.logon = Fle_SQliteWindow()self.logon.show()#self.hide()#人臉數據庫展示界面 class Fle_SQliteWindow(QDialog,Ui_Dialog_SQliteWindow):def __init__(self):super(Fle_SQliteWindow,self).__init__()self.setupUi(self)self.tableView.setModel(mysqlite.model)self.pushButton_add.clicked.connect(self.addrow)self.pushButton_delete.clicked.connect(lambda: mysqlite.model.removeRow(self.tableView.currentIndex().row()))def addrow(self):# 不是在QTableView上添加,而是在模型上添加,會自動將數據保存到數據庫中!# 參數一:數據庫共有幾行數據 參數二:添加幾行ret = mysqlite.model.insertRows(mysqlite.model.rowCount(), 1) # 返回是否插入print('數據庫共有%d行數據' % mysqlite.model.rowCount())print('insertRow=%s' % str(ret))#數據庫操作類 class Fle_Sqlite():def __init__(self):self.db = QSqlDatabase.addDatabase('QSQLITE')self.db.setDatabaseName('./people_data.db')if not self.db.open():print('無法建立與數據庫的連接')query = QSqlQuery()query.exec('create table people(id varcahr(10),xuehao varcahr(15),name varcahr(50))')self.model = QSqlTableModel() # MVC模式中的模型# 初始化將數據裝載到模型當中self.initializeModel()# 初始化def initializeModel(self):self.model.setTable('people')# 當字段變化時會觸發一些事件self.model.setEditStrategy(QSqlTableModel.OnFieldChange)# 將整個數據裝載到model中self.model.select()# 設置字段頭#只是設置字段頭,不是顯示self.model.setHeaderData(0, Qt.Horizontal, 'ID')self.model.setHeaderData(1, Qt.Horizontal, 'xuehao')self.model.setHeaderData(2, Qt.Horizontal, 'name')#找指定位置的數據def find_data(self, row, col):# 序號從0開始index = self.model.index(row, col)return self.model.data(index)#新加一行def add_row(self,ID,xuehao,name):row = self.model.rowCount()self.model.insertRow(row) self.model.setData(self.model.index(row, 0), ID) self.model.setData(self.model.index(row, 1), xuehao) self.model.setData(self.model.index(row, 2), name) self.model.submitAll()print(ID)print(xuehao)print(name)#刪除最后一行def del_row(self):row = self.model.rowCount()-1self.model.removeRow(row)self.model.submitAll()def get_rows(self):#print(self.model.rowCount())return self.model.rowCount()if __name__ == "__main__":mysqlite=Fle_Sqlite()app = QApplication(sys.argv)w = Fle_MainWindow()w.show()sys.exit(app.exec_())

3、運行結果:


由上面兩圖可以看出識別效果正確。

識別出人臉時亮綠燈。


由上圖可知,顯示“不認識”時亮紅燈。

六、總結與體會

①本次實驗采用的LBPH人臉識別模型精度欠缺,受光線影響非常嚴重,或許可以通過攝像頭加紅外濾光片外加紅外補光燈解決。
②本次實驗中多次遇到攝像頭調用打開不了導致imread出錯的情況,具體原因沒有找到,猜測是攝像頭的序列號改變了。
③本次實驗中創建了多個界面類,而人臉識別界面類和人臉錄入界面類都需要調用攝像頭,導致了攝像頭經常報錯,所以在界面切換的時候關掉了攝像頭,在界面初始化的時候又打開了攝像頭,但是這樣做有時也會造成攝像頭來不及釋放而報錯。
④對于數據庫的操作,卡了很長的時間才分清楚數據庫和數據表的區別,最后才搞清楚讀寫操作都是對鏈接到數據庫的數據表操作。

附錄

代碼:https://gitee.com/guoxianda/face-recognition-base-on-Raspberry-pie

總結

以上是生活随笔為你收集整理的基于树莓派的人脸识别门禁系统的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。