Python | 人脸识别系统 — 用户操作
本博客為人臉識別系統的攝像頭畫面展示代碼解釋
人臉識別系統博客匯總:人臉識別系統-博客索引
項目GitHub地址:Su-Face-Recognition: A face recognition for user logining
注意:閱讀本博客前請先參考以下博客
工具安裝、環境配置:人臉識別系統-簡介
UI界面設計:人臉識別系統-UI界面設計
UI事件處理:人臉識別系統-UI事件處理
人臉識別:人臉識別系統-人臉識別
活體檢測:人臉識別系統-活體檢測
閱讀完本博客后可以繼續閱讀:
攝像頭畫面展示:人臉識別系統-攝像頭畫面展示
用戶端邏輯:
- 人臉識別:Python | 人臉識別系統 — 人臉識別
- 活體檢測:Python | 人臉識別系統 — 活體檢測
- 背景模糊:Python | 人臉識別系統 — 背景模糊
- 姿態檢測:Python | 人臉識別系統 — 姿態檢測
- 人臉比對:Python | 人臉識別系統 — 人臉比對
管理員端邏輯:
- 管理員操作:
- 用戶操作:
一、用戶登錄
????????1、登錄邏輯
????????信息核驗(數據庫) -> 靜默活體檢測?-> 交互活體檢測?-> 人臉識別?
? ? ? ? 一旦用戶超過三次沒有登錄成功(活體檢測/人臉識別不成功),系統將當前用戶進行鎖定。用戶需要通過管理員進行解鎖。
# 登錄標志USER_LOGIN_MSG_FLAG = False # 用戶信息核驗成功標志USER_LOGIN_FLAG = False # 用戶登錄成功標志... ...# 用戶登錄def user_login(self):if not self.cap.isOpened():QMessageBox.information(self, "提示", self.tr("請先打開攝像頭"))else:global USER_LOGIN_FLAGif not USER_LOGIN_FLAG:QApplication.processEvents()login = LoginWindow(self) # 創建信息核驗界面對象login.exec_() global USER_LOGIN_MSG_FLAGglobal USER_LOGIN_NAMEif USER_LOGIN_MSG_FLAG:# 登錄信息成功,進行活體檢測QMessageBox.about(self, '提示', '登錄成功,進行活體檢測')if self.detect_face():# 活體檢測成功,進行人臉識別global ENCODING_TEMPface_encoding = FaceEncodingUtil.decoding_FaceStr(ENCODING_TEMP)if self.recognize_instant_face(face_encoding):QMessageBox.about(self, '提示', '登陸成功')self.save_record(USER_LOGIN_NAME, '使用攝像頭進行登錄') # 使用excel表格進行保存USER_LOGIN_FLAG = Trueelse:QMessageBox.about(self, '提示', '人臉識別失敗,請重新登錄')if USER_LOGIN_NAME != "":UserSqlUtil.add_name_warn(USER_LOGIN_NAME)USER_LOGIN_MSG_FLAG = Falseelse:QMessageBox.about(self, '提示', '活體檢測失敗,請重新登錄')if USER_LOGIN_NAME != "":UserSqlUtil.add_name_warn(USER_LOGIN_NAME)USER_LOGIN_MSG_FLAG = Falselogin.destroy()else:QMessageBox.about(self, '提示', '用戶已經登錄')? ? ? ? 2、信息核驗
????????用戶點擊 [用戶登錄] 按鈕,主界面彈出信息核驗界面,要求用戶輸入賬號、密碼。點擊確認后,系統訪問數據庫,判斷輸入信息是否正確。
? ? ? ? 信息核驗界面相關代碼:
# 用戶登錄界面 class LoginWindow(QDialog, LoginMsgUi):def __init__(self, parent=None):super(LoginWindow, self).__init__(parent)self.setupUi(self)self.minimize_button.clicked.connect(self.showMinimized)self.close_button.clicked.connect(self.cancel_login)self.confirm_button.clicked.connect(self.search_user)self.cancel_button.clicked.connect(self.cancel_login)# 點擊確認,搜索用戶def search_user(self):input_name = self.name_lineEdit.text()input_password = self.password_lineEdit.text()if input_name == "":QMessageBox.about(self, '提示', '姓名不能為空')elif input_password == "":QMessageBox.about(self, '提示', '密碼不能為空')else:row = UserSqlUtil.search_by_name("\"" + input_name + "\"")if row:result = row[0]password = result[1]if input_password != password:QMessageBox.about(self, '提示', '密碼輸入錯誤')else:global USER_LOGIN_MSG_FLAGcount = UserSqlUtil.search_count_warn("\"" + input_name + "\"")if count >= 3:QMessageBox.about(self, '警告', '該賬號目前已被鎖定')USER_LOGIN_MSG_FLAG = Falseelse:global ENCODING_TEMPglobal USER_LOGIN_NAMEUSER_LOGIN_MSG_FLAG = TrueENCODING_TEMP = result[5]USER_LOGIN_NAME = input_nameself.close_window()else:QMessageBox.about(self, '提示', '該用戶不存在')# 點擊取消按鈕def cancel_login(self):global USER_LOGIN_MSG_FLAGUSER_LOGIN_MSG_FLAG = Falseself.close_window()# 關閉窗口def close_window(self):self.name_lineEdit.setPlaceholderText("請輸入姓名")self.password_lineEdit.setPlaceholderText("請輸入密碼")self.close()? ? ? ? 數據庫表結構(user表)
? ? ? ? 數據庫代碼
# -*- coding: utf-8 -*- import pymysqldef init_conn():conn = pymysql.connect(host="127.0.0.1", # 數據庫的IP地址user="root", # 數據庫用戶名稱password="root", # 數據庫用戶密碼db="contest", # 數據庫名稱port=3306, # 數據庫端口名稱charset="utf8" # 數據庫的編碼方式)return conndef execute_with_bool(sql_str, args=()):conn = init_conn()cursor = conn.cursor()try:cursor.execute(sql_str, args)conn.commit()return Trueexcept Exception as e:conn.rollback()print(e)return Falsefinally:cursor.close()def execute_with_list(sql_str):conn = init_conn()cursor = conn.cursor()results = []try:cursor.execute(sql_str)results = cursor.fetchall()except Exception as e:conn.rollback()print(e)finally:cursor.close()return resultsdef insert_data(name, password, age, sex, more, face_encoding):return execute_with_bool("insert into user(name,password,age,sex,more,face_encoding) values(%s,%s,%s,%s,%s,%s)",(name, password, age, sex, more, face_encoding))def update_by_name(name, password, age, sex, more, face_encoding):return execute_with_bool("update user set name=%s,password=%s,age=%s,sex=%s,more=%s,face_encoding=%s where name = %s",(name, password, age, sex, more, face_encoding, name))def update_by_name_without_encoding(name, age, sex, more):return execute_with_bool("update user set name=%s,age=%s,sex=%s,more=%s where name = %s",(name, age, sex, more, name))def search_all_msg():return execute_with_list("select * from user")def search_by_name(name):return execute_with_list("select * from user where name = " + name)def search_count_name(name):return execute_with_list("select count(*) from user where name = " + name)[0][0]def delete_by_name(name):return execute_with_bool("delete from user where name = %s", name)def search_count_warn(name):return execute_with_list("select count(*) from warn where name = " + name)[0][0]def add_name_warn(name):return execute_with_bool("insert into warn(name) values(%s)", name)? ? ? ? 3、活體檢測
活體檢測函數?detect_face() 詳見博客:
? ? ? 4、人臉識別
人臉識別函數 recognize_instant_face() 詳見博客:
人臉識別使用的是函數 recognize_instant_face(),其中需要參數face_encoding,為1*128的矩陣。當我們從數據庫取出當前登錄用戶的人臉編碼時,為字符串類型,需要進行轉換。編寫工具類FaceEncodingUtil,調用編寫的方法?decoding_FaceStr 進行轉換。其工具類方法如下:
# -*- coding: utf-8 -*- import numpydef decoding_FaceStr(encoding_str):# 將字符串轉為numpy ndarray類型,即矩陣# 轉換成一個listdecoding_list = encoding_str.strip(' ').split(',')# 將list中str轉換為floatdecoding_float = list(map(float, decoding_list))face_encoding = numpy.array(decoding_float)return face_encoding二、用戶注冊
? ? ? ? 1、判斷器
? ? ? ? 攝像頭截取當前人臉 -> 信息填寫 -> 面部信息編碼 -> 信息保存(數據庫)
????????攝像頭截取當前人臉照片,使用當前時間點作為照片名保存到photo目錄下,面部信息編碼成功后刪除照片。
signal_register = pyqtSignal() # 用戶注冊 界面信號... ...# 用戶注冊def user_register(self):isCapOpened_flag = self.cap.isOpened()if not isCapOpened_flag:QMessageBox.information(self, "提示", self.tr("請先打開攝像頭!"))else:ret, frame = self.cap.read()frame_location = face_recognition.face_locations(frame)if len(frame_location) == 0:QMessageBox.information(self, "提示", self.tr("沒有檢測到人臉,請重新拍攝!"))else:QMessageBox.information(self, "提示", self.tr("拍照成功!"))global PHOTO_FOLDER_PATHglobal SHOT_TEMP_NAMESHOT_TEMP_NAME = datetime.now().strftime("%Y%m%d%H%M%S")self.show_image.save(PHOTO_FOLDER_PATH + SHOT_TEMP_NAME + ".jpg")self.send_signal_register()# 發射信號 打開注冊用戶界面def send_signal_register(self):self.signal_register.emit()? ? ? ? 2、邏輯編寫
????????用戶點擊 [用戶注冊] 按鈕,主界面彈出信息填寫界面,要求用戶輸入賬號、密碼等信息。點擊確認后,系統判斷輸入信息格式是否正確。
# 用戶注冊界面 class RegisterWindow(QMainWindow, RegisterMsgUi):def __init__(self, parent=None):super(RegisterWindow, self).__init__(parent)self.setupUi(self)self.minimize_button.clicked.connect(self.showMinimized)self.close_button.clicked.connect(self.close_window)self.cancel_button.clicked.connect(self.delete_shot)self.confirm_button.clicked.connect(self.fill_information)# 填寫信息def fill_information(self):flag = 0name = self.name_lineEdit.text()password = self.password_lineEdit.text()age = self.age_lineEdit.text()sex = self.sex_lineEdit.text()more_infor = self.more_lineEdit.text()if self.judge_name_conflict(name):if name != '':# 輸入密碼if password != '':# 輸入年齡if age == '':age = '未知'elif not str.isdigit(age):flag = 1QMessageBox.about(self, '提示', '請輸入正確的年齡格式')# 輸入性別if sex == '':sex = '未知'elif sex != '男' and sex != '女':flag = 1QMessageBox.about(self, '提示', '請輸入正確的性別格式')sex = '未知'# 輸入更多信息if more_infor == '':more_infor = '未知'global PHOTO_FOLDER_PATHglobal SHOT_TEMP_NAMEif flag == 0:# 計算臉部數據并保存到數據庫QApplication.processEvents()register_encoding = self.analyse_encoding(SHOT_TEMP_NAME)if self.save_database(name, password, age, sex, more_infor, register_encoding):QMessageBox.about(self, '提示', '完成注冊')else:QMessageBox.about(self, '提示', '注冊失敗')self.delete_shot()elif flag == 1:QMessageBox.about(self, '提示', '注冊失敗')else:QMessageBox.about(self, '提示', '請輸入密碼')else:QMessageBox.about(self, '提示', '請輸入姓名')else:QMessageBox.about(self, '提示', '用戶' + name + '已經注冊過')# 保存注冊信息@staticmethoddef save_database(name, password, age, sex, more, face_encoding):return UserSqlUtil.insert_data(name, password, age, sex, more, face_encoding)# 判斷姓名是否沖突@staticmethoddef judge_name_conflict(name):count = UserSqlUtil.search_count_name("\"" + name + "\"")if count != 0:return Falseelse:return True# 分析截圖@staticmethoddef analyse_encoding(name):global PHOTO_FOLDER_PATHphoto_path = PHOTO_FOLDER_PATH + name + ".jpg"register_images = face_recognition.load_image_file(photo_path)register_encoding = face_recognition.face_encodings(register_images)[0]return FaceEncodingUtil.encoding_FaceStr(register_encoding)# 刪除截圖def delete_shot(self):global PHOTO_FOLDER_PATHglobal SHOT_TEMP_NAMEdelete_shot_path = PHOTO_FOLDER_PATH + SHOT_TEMP_NAME + ".jpg"os.remove(delete_shot_path)SHOT_TEMP_NAME = ""self.close_window()# 關閉窗口def close_window(self):lineText = [self.age_lineEdit, self.sex_lineEdit, self.name_lineEdit, self.more_lineEdit]line = 0for lineEdit in lineText:lineEdit.setPlaceholderText(str(line))if 3 >= line >= 0:lineEdit.setPlaceholderText("請輸入信息")line = line + 1self.close()進行數據庫保存的時候,面部編碼數據為為1*128的矩陣,需要通過工具類FaceEncodingUtil的方法?encoding_FaceStr 進行轉換。其工具類方法如下:
# -*- coding: utf-8 -*- import numpydef encoding_FaceStr(image_face_encoding):# 將numpy array類型轉化為列表encoding__array_list = image_face_encoding.tolist()# 將列表里的元素轉化為字符串encoding_str_list = [str(i) for i in encoding__array_list]# 拼接列表里的字符串encoding_str = ','.join(encoding_str_list)return encoding_str三、用戶登出
? ? ? ? 用戶登出操作比較簡單,將全局標志 USER_LOGIN_FLAG 設置為False即可。
????????判斷器代碼如下:
# 用戶登出def user_logout(self):global USER_LOGIN_FLAGglobal USER_LOGIN_NAMEif not USER_LOGIN_FLAG:QMessageBox.about(self, '提示', '請先登錄')else:USER_LOGIN_FLAG = FalseQMessageBox.about(self, '提示', '退出成功')self.save_record(USER_LOGIN_NAME, '退出登錄') # 記錄到excel表格中四、Excel表格記錄
? ? ? ? 將用戶登錄、登出的操作時間、設備、用戶名等信息保存到系統excel表格中。可以通過管理員身份登錄系統,導出系統的excel表格進行查看。導出excel表格的代碼在管理員端編寫。
? ? ? ? 保存信息到excel表格的代碼如下:
# 將記錄保存到excel中@staticmethoddef save_record(name, record):global DATA_FOLDER_PATHlocal_path = DATA_FOLDER_PATH + 'history.xls'old_book = xlrd.open_workbook(local_path)new_book = copy(old_book)sheet2 = new_book.get_sheet(0)sheet0 = old_book.sheet_by_index(0)n_rows = sheet0.nrowsstr_time = datetime.now().strftime("%Y-%m-%d %H:%M:%S")sheet2.write(n_rows + 1, 0, str_time)sheet2.write(n_rows + 1, 1, '攝像頭')sheet2.write(n_rows + 1, 2, name)sheet2.write(n_rows + 1, 3, record)new_book.save('new_book.xls')os.remove(local_path)os.rename('new_book.xls', local_path)????????
閱讀完本博客后可以繼續閱讀:
攝像頭畫面展示:人臉識別系統-攝像頭畫面展示
用戶端邏輯:
- 人臉識別:Python | 人臉識別系統 — 人臉識別
- 活體檢測:Python | 人臉識別系統 — 活體檢測
- 背景模糊:Python | 人臉識別系統 — 背景模糊
- 姿態檢測:Python | 人臉識別系統 — 姿態檢測
- 人臉比對:Python | 人臉識別系統 — 人臉比對
管理員端邏輯:
- 管理員操作:
- 用戶操作:
注:以上代碼僅為參考,若需要運行,請參考項目GitHub完整源代碼:?Su-Face-Recognition: A face recognition for user logining
總結
以上是生活随笔為你收集整理的Python | 人脸识别系统 — 用户操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: htc android sd卡,HTC
- 下一篇: 软件测试拿了几个20K offer,分享