環(huán)保設(shè)備網(wǎng)站怎么做手機(jī)百度云電腦版入口
【舊文更新】【優(yōu)秀畢設(shè)】人臉識別打卡/簽到/考勤管理系統(tǒng)(OpenCV+最簡基本庫開發(fā)、可移植樹莓派 擴(kuò)展網(wǎng)絡(luò)圖像推流控制 驗(yàn)證碼及Excel郵件發(fā)送等功能)
文章目錄
- 關(guān)于舊文新發(fā)
- 畢設(shè)結(jié)構(gòu)
- 主頁面
- 驗(yàn)證碼
- 識別效果
- 管理頁面
- 人臉信息采集
- 管理
- 實(shí)時(shí)數(shù)據(jù)更新
- 簽到結(jié)果
- 郵件發(fā)送
- 網(wǎng)絡(luò)前端效果
- 實(shí)時(shí)圖像推流
- 附錄:列表的賦值類型和py打包
- 列表賦值
- BUG復(fù)現(xiàn)
- 代碼改進(jìn)
- 優(yōu)化
- 總結(jié)
- py打包
- 附錄:關(guān)于舊文新發(fā)
關(guān)于舊文新發(fā)
為何要進(jìn)行舊文新發(fā)?
因?yàn)槲以?023年博客之星評選中發(fā)現(xiàn) 有的人轉(zhuǎn)載、抄襲他人文章 稍微改動幾下也能作為高質(zhì)量文章入選
所以我將把我的舊文重新發(fā)一次 然后也這樣做
2023年博客之星規(guī)則:
畢設(shè)結(jié)構(gòu)
該系統(tǒng)利用Harr級聯(lián)檢測和LPBH進(jìn)行人臉檢測和訓(xùn)練、識別
利用Tkinter完成界面搭建
利用Flask+HTML完成網(wǎng)絡(luò)實(shí)時(shí)圖像推流及控制
利用captcha.image 完成驗(yàn)證碼功能
利用xlsxwriter將數(shù)據(jù)保存為Excel文檔
利用email庫發(fā)送郵件
功能如下圖所示 所有功能均可實(shí)現(xiàn)
cv2版本: 推薦4.4.0.46 安裝opencv-python和opencv-contrib-python
部分資源:
download.csdn.net/download/weixin_53403301/85545163
基礎(chǔ)完整資源:
download.csdn.net/download/weixin_53403301/85744946
視頻:
【優(yōu)秀畢設(shè)開源】人臉識別打卡/簽到/考勤管理系統(tǒng)(OpenCV+最簡基本庫反向開發(fā)、可移植樹莓派 擴(kuò)展網(wǎng)絡(luò)圖像推流控制 驗(yàn)證碼及Excel郵件發(fā)送等功能)
【優(yōu)秀畢設(shè)開源】基于OpenCV的人臉識別打卡/簽到/考勤管理系統(tǒng)(最簡基本庫開發(fā)、可基于樹莓派)
部分代碼:
# -*- coding: utf-8 -*-
"""
Created on Mon May 31 23:39:19 2021@author: ZHOU
"""# -*- coding: utf-8 -*-
import tkinter as tk # 調(diào)用窗口tk
from tkinter import ttk
from tkinter.filedialog import askopenfilename
import tkinter.messagebox
from PIL import Image, ImageTk, ImageDraw, ImageFont # 調(diào)用圖像處理庫pillow
import cv2 # 調(diào)用OpenCV圖像處理庫
import threading # 調(diào)用threading多線程運(yùn)行庫
import time # 調(diào)用系統(tǒng)時(shí)間戳庫
import os # 調(diào)用os多操作系統(tǒng)接口庫
import re
import numpy as np
from captcha.image import ImageCaptcha
import random
import string
import xlsxwriter
import smtplib
import email.mime.multipart
import email.mime.text
from email.mime.application import MIMEApplication
from flask import Flask,render_template, request, Response
import socketglobal network_flag
network_flag = 0
local_post = 1212
local_ip = None
for i in range(12):try:s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)s.connect(("8.8.8.8",80))local_ip = str(s.getsockname()[0])s.close()print("Network Enable")network_flag = 1breakexcept: print("Network Error...")network_flag = 0time.sleep(5)app = Flask(__name__)star_pic_path = "./star.png"
pic_path = "./dataset"
train_path = "./trainer"
data_path = "./data"
train_nb_path = "/train_nb.txt"
train_time_path = "/train_time.txt"
name_id_path = "/name_id.txt"
email_set_path = "/email_set.txt"
admin_path = "/admin.txt"
yml_path = "/trainer.yml"
temp_path = "./temp"
save_path = "./save"
date_path = "/date.txt"
sign_in_mode_path = "/sign_in_mode.txt"
company_path = "/company.txt"
department_path = "/department.txt"
class_id_path = "/class_id.txt"
global today_temp_path
now_today = time.time()
today_temp_path = "/today_"+str(time.localtime(now_today).tm_year)+"_"+str(time.localtime(now_today).tm_mon)+"_"+str(time.localtime(now_today).tm_mday)+".txt"cascadePath = "./cascade/haarcascade_frontalface_alt2.xml"
faceCascade = cv2.CascadeClassifier(cascadePath)
font = cv2.FONT_HERSHEY_SIMPLEXrecognizer = cv2.face.LBPHFaceRecognizer_create()
try:recognizer.read(train_path+yml_path)
except:print("缺失訓(xùn)練數(shù)據(jù)文件,請先訓(xùn)練數(shù)據(jù)")cam_flag = 0global img2
img2 = None
global img_flag
img_flag = 0
global login_flag
login_flag = 0
global doing_change_record_date_flag
doing_change_record_date_flag = 0
global auto_send_flag
auto_send_flag = 0
# -*- coding: utf-8 -*-
"""
Created on Mon Apr 25 23:25:45 2022@author: 16016
"""import xlsxwriter
import timedef txt_excel(filename):fp = open(filename,encoding="utf-8")x = 0y = 0lines = fp.readlines()today_list = (lines[0].split("\n")[0]).split("-")xls = xlsxwriter.Workbook('record_' + today_list[0]+"_"+today_list[1]+"_"+today_list[2] + '.xlsx')sheet = xls.add_worksheet('record_' + today_list[0]+"_"+today_list[1]+"_"+today_list[2]) sheet.write(0,0,"姓名")for j in lines:for i in range(1,len(j.split('|'))):item = j.split('|')[i].strip(' ')sheet.write(x,y,item)y += 1 # 另起一列x += 1 # 另起一行y = 0 # 初始成第一列 fp.close()xls.close()filename = './temp/today_2022_4_25.txt'
xlsname = './save/學(xué)生簽到表'
txt_excel(filename)
<html><meta http-equiv="refresh" content="60"> <head><title>人臉識別簽到管理系統(tǒng)</title></head> <body><h1>人臉識別簽到管理系統(tǒng)</h1><form action="/" method="post"><p><input type="submit" style="font-size:50px" name="send" value="發(fā)送數(shù)據(jù)"> <input type="submit" style="font-size:50px" name="maul" value="刷新網(wǎng)頁"></p><p><table>{% for k,v in data_dict.items() %}<tr><td>{{k}}</td><td>{{v[0]}}</td><td>{{v[1]}}</td><td>{{v[2]}}</td><td>{{v[3]}}</td><td>{{v[4]}}</td></tr>{% endfor %}</table></p><p><input type="submit" style="font-size:50px" name="update" value="更新記錄日期"> <input type="submit" style="font-size:50px" name="back" value="回退記錄日期"></p> </form> <img src="{{ url_for('video_feed') }}" height="520" style="float:left"></body>
</html>
# -*- coding: utf-8 -*-
"""
Created on Tue Apr 26 15:16:42 2022@author: 16016
"""#!/usr/bin/python
# -*- coding: UTF-8 -*-
import smtplib
import email.mime.multipart
import email.mime.text
from email.mime.application import MIMEApplicationdef send_email(file_path,smtp_host, smtp_port, sendAddr, password, recipientAddrs, subject='', content=''):''':param smtp_host: 域名:param smtp_port: 端口:param sendAddr: 發(fā)送郵箱:param password: 郵箱密碼:param recipientAddrs: 發(fā)送地址:param subject: 標(biāo)題:param content: 內(nèi)容:return: 無'''msg = email.mime.multipart.MIMEMultipart()msg['from'] = sendAddrmsg['to'] = recipientAddrsmsg['subject'] = subjectcontent = contenttxt = email.mime.text.MIMEText(content, 'plain', 'utf-8')msg.attach(txt)if file_path != '':# 添加附件地址part = MIMEApplication(open(file_path, 'rb').read())part.add_header('Content-Disposition', 'attachment', filename="name_id.xlsx") # 發(fā)送文件名稱msg.attach(part)try:smtpSSLClient = smtplib.SMTP_SSL(smtp_host, smtp_port) # 實(shí)例化一個(gè)SMTP_SSL對象loginRes = smtpSSLClient.login(sendAddr, password) # 登錄smtp服務(wù)器print(f"登錄結(jié)果:loginRes = {loginRes}") # loginRes = (235, b'Authentication successful')if loginRes and loginRes[0] == 235:print(f"登錄成功,code = {loginRes[0]}")smtpSSLClient.sendmail(sendAddr, recipientAddrs, str(msg))print(f"mail has been send successfully. message:{str(msg)}")smtpSSLClient.quit()else:print(f"登陸失敗,code = {loginRes[0]}")except Exception as e:print(f"發(fā)送失敗,Exception: e={e}")try:subject = 'Python 測試郵件'content = '這是一封來自 Python 編寫的測試郵件。'send_email('','smtp.qq.com', 465, '', '', '', subject, content)
except Exception as err:print(err)
主頁面
驗(yàn)證碼
識別效果
管理頁面
數(shù)據(jù)保存除了用戶信息和簽到信息外 還可以判斷是否遲到、早退并計(jì)算工作時(shí)長
人臉信息采集
管理
實(shí)時(shí)數(shù)據(jù)更新
簽到結(jié)果
郵件發(fā)送
網(wǎng)絡(luò)前端效果
實(shí)時(shí)圖像推流
(在識別時(shí)(IN/OUT功能)會推流到網(wǎng)絡(luò)中 管理員通過IP地址可以實(shí)現(xiàn)監(jiān)控效果)
附錄:列表的賦值類型和py打包
列表賦值
BUG復(fù)現(xiàn)
閑來無事寫了個(gè)小程序 代碼如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序號:",j)print('a_list:\n',a_list)c_list[j]=a_listprint('c_list[0]:\n',c_list[0])print('\n')
# b_list[j]=a_list[7],a_list[8]
# print(b_list[j])# 寫入到Excel:
#print(c_list,'\n')
我在程序中 做了一個(gè)16次的for循環(huán) 把列表a的每個(gè)值后面依次加上"_"和循環(huán)序號
比如循環(huán)第x次 就是把第x位加上_x 這一位變成x_x 我在輸出測試中 列表a的每一次輸出也是對的
循環(huán)16次后列表a應(yīng)該變成[‘0_0’, ‘1_1’, ‘2_2’, ‘3_3’, ‘4_4’, ‘5_5’, ‘6_6’, ‘7_7’, ‘8_8’, ‘9_9’, ‘10_10’, ‘11_11’, ‘12_12’, ‘13_13’, ‘14_14’, ‘15_15’] 這也是對的
同時(shí) 我將每一次循環(huán)時(shí)列表a的值 寫入到空列表c中 比如第x次循環(huán) 就是把更改以后的列表a的值 寫入到列表c的第x位
第0次循環(huán)后 c[0]的值應(yīng)該是[‘0_0’, ‘1’, ‘2’, ‘3’, ‘4’, ‘5’, ‘6’, ‘7’, ‘8’, ‘9’, ‘10’, ‘11’, ‘12’, ‘13’, ‘14’, ‘15’] 這也是對的
但是在第1次循環(huán)以后 c[0]的值就一直在變 變成了c[x]的值
相當(dāng)于把c_list[0]變成了c_list[1]…以此類推 最后得出的列表c的值也是每一項(xiàng)完全一樣
我不明白這是怎么回事
我的c[0]只在第0次循環(huán)時(shí)被賦值了 但是后面它的值跟著在改變
如圖:
第一次老出bug 賦值以后 每次循環(huán)都改變c[0]的值 搞了半天都沒搞出來
無論是用appen函數(shù)添加 還是用二維數(shù)組定義 或者增加第三個(gè)空數(shù)組來過渡 都無法解決
代碼改進(jìn)
后來在我華科同學(xué)的指導(dǎo)下 突然想到賦值可以賦的是個(gè)地址 地址里面的值一直變化 導(dǎo)致賦值也一直變化 于是用第二張圖的循環(huán)套循環(huán)深度復(fù)制實(shí)現(xiàn)了
代碼如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序號:",j)print('a_list:\n',a_list)for i in range(16):c_list[j].append(a_list[i])print('c_list[0]:\n',c_list[0])print('\n')
# b_list[j]=a_list[7],a_list[8]
# print(b_list[j])# 寫入到Excel:
print(c_list,'\n')
解決了問題
優(yōu)化
第三次是請教了老師 用copy函數(shù)來賦真值
代碼如下:
# -*- coding: utf-8 -*-
"""
Created on Fri Nov 19 19:47:01 2021@author: 16016
"""a_list = ['0','1','2','3','4','5','6','7','8','9','10','11','12','13','14','15']
#print(len(a_list))
#b_list = ['','','','','','','','','','','','','','','','']
c_list = [[],[],[],[],[],[],[],[],[],[],[],[],[],[],[],[]]
#for i in range(16):
if len(a_list):for j in range(16):a_list[j]=str(a_list[j])+'_'+str(j)print("序號:",j)print('a_list:\n',a_list)c_list[j]=a_list.copy()print('c_list[0]:\n',c_list[0])print('\n')
# b_list[j]=a_list[7],a_list[8]
# print(b_list[j])# 寫入到Excel:
#print(c_list,'\n')
同樣能解決問題
最后得出問題 就是指針惹的禍!
a_list指向的是個(gè)地址 而不是值 a_list[i]指向的才是單個(gè)的值 copy()函數(shù)也是復(fù)制值而不是地址
如果這個(gè)用C語言來寫 就直觀一些了 難怪C語言是基礎(chǔ) 光學(xué)Python不學(xué)C 遇到這樣的問題就解決不了
C語言yyds Python是什么垃圾弱智語言
總結(jié)
由于Python無法單獨(dú)定義一個(gè)值為指針或者獨(dú)立的值 所以只能用列表來傳送
只要賦值是指向一個(gè)列表整體的 那么就是指向的一個(gè)指針內(nèi)存地址 解決方法只有一個(gè) 那就是將每個(gè)值深度復(fù)制賦值(子列表內(nèi)的元素提取出來重新依次連接) 或者用copy函數(shù)單獨(dú)賦值
如圖測試:
部分代碼:
# -*- coding: utf-8 -*-
"""
Created on Sat Nov 20 16:45:48 2021@author: 16016
"""def text1():A=[1,2,3]B=[[],[],[]]for i in range(len(A)):A[i]=A[i]+iB[i]=Aprint(B)def text2():A=[1,2,3]B=[[],[],[]]A[0]=A[0]+0B[0]=Aprint(B)A[1]=A[1]+1B[1]=Aprint(B)A[2]=A[2]+2B[2]=Aprint(B)if __name__ == '__main__':text1()print('\n')text2()
py打包
Pyinstaller打包exe(包括打包資源文件 絕不出錯(cuò)版)
依賴包及其對應(yīng)的版本號
PyQt5 5.10.1
PyQt5-Qt5 5.15.2
PyQt5-sip 12.9.0
pyinstaller 4.5.1
pyinstaller-hooks-contrib 2021.3
Pyinstaller -F setup.py 打包exe
Pyinstaller -F -w setup.py 不帶控制臺的打包
Pyinstaller -F -i xx.ico setup.py 打包指定exe圖標(biāo)打包
打包exe參數(shù)說明:
-F:打包后只生成單個(gè)exe格式文件;
-D:默認(rèn)選項(xiàng),創(chuàng)建一個(gè)目錄,包含exe文件以及大量依賴文件;
-c:默認(rèn)選項(xiàng),使用控制臺(就是類似cmd的黑框);
-w:不使用控制臺;
-p:添加搜索路徑,讓其找到對應(yīng)的庫;
-i:改變生成程序的icon圖標(biāo)。
如果要打包資源文件
則需要對代碼中的路徑進(jìn)行轉(zhuǎn)換處理
另外要注意的是 如果要打包資源文件 則py程序里面的路徑要從./xxx/yy換成xxx/yy 并且進(jìn)行路徑轉(zhuǎn)換
但如果不打包資源文件的話 最好路徑還是用作./xxx/yy 并且不進(jìn)行路徑轉(zhuǎn)換
def get_resource_path(relative_path):if hasattr(sys, '_MEIPASS'):return os.path.join(sys._MEIPASS, relative_path)return os.path.join(os.path.abspath("."), relative_path)
而后再spec文件中的datas部分加入目錄
如:
a = Analysis(['cxk.py'],pathex=['D:\\Python Test\\cxk'],binaries=[],datas=[('root','root')],hiddenimports=[],hookspath=[],hooksconfig={},runtime_hooks=[],excludes=[],win_no_prefer_redirects=False,win_private_assemblies=False,cipher=block_cipher,noarchive=False)
而后直接Pyinstaller -F setup.spec即可
如果打包的文件過大則更改spec文件中的excludes 把不需要的庫寫進(jìn)去(但是已經(jīng)在環(huán)境中安裝了的)就行
這些不要了的庫在上一次編譯時(shí)的shell里面輸出
比如:
然后用pyinstaller --clean -F 某某.spec
附錄:關(guān)于舊文新發(fā)
為何要進(jìn)行舊文新發(fā)?
因?yàn)槲以?023年博客之星評選中發(fā)現(xiàn) 有的人轉(zhuǎn)載、抄襲他人文章 稍微改動幾下也能作為高質(zhì)量文章入選
所以我將把我的舊文重新發(fā)一次 然后也這樣做
2023年博客之星規(guī)則: