
本文针对基于OpenCV和face_recognition库构建的人脸识别考勤系统,解决了在摄像头持续识别人脸时,重复将考勤记录写入CSV文件的问题。通过调整代码逻辑,确保每个人只记录一次考勤信息,并提供优化建议,提高程序效率。
在构建人脸识别考勤系统时,一个常见的挑战是避免重复记录考勤信息。以下将详细介绍如何修改代码,确保每个人只记录一次考勤,并提供一些优化建议。
问题分析
原始代码在主循环中,每次检测到人脸匹配时,都会调用 markAttendance 函数。由于摄像头帧率很高,即使人脸只出现一次,也会被多次检测到,导致重复写入 CSV 文件。
解决方案
核心思路是:在将姓名写入文件之前,先检查该姓名是否已经存在于已记录的姓名列表中。如果存在,则跳过写入操作;否则,才进行写入。以下是修改后的 markAttendance 函数:
from datetime import datetimedef markAttendance(name): with open('Attendance.csv', 'r+') as f: myDataList = f.readlines() nameList = [] for line in myDataList: entry = line.split(',') nameList.append(entry[0]) if name not in nameList: now = datetime.now() dtString = now.strftime('%H:%M:%S') f.writelines(f'n{name},{dtString}')
代码解释:
读取现有数据: f.readlines() 读取整个文件的所有行,并将其存储在 myDataList 列表中。提取已记录的姓名: 循环遍历 myDataList,将每一行按照逗号分隔,提取出姓名,并将其添加到 nameList 列表中。检查姓名是否已存在: 使用 if name not in nameList: 判断当前检测到的姓名是否已经存在于 nameList 中。写入考勤记录: 如果姓名不存在,则获取当前时间,格式化为字符串,并将姓名和时间写入 CSV 文件。
优化建议
虽然上述代码可以解决重复写入的问题,但每次调用 markAttendance 函数时都读取整个 CSV 文件效率较低。可以进行以下优化:
在程序启动时读取姓名列表: 在程序启动时,一次性读取 CSV 文件中的所有姓名,并将其存储在内存中。更新内存中的姓名列表: 每次成功写入新的考勤记录后,立即将该姓名添加到内存中的姓名列表中。使用 “a” 模式打开文件: 在markAttendance函数中使用追加模式 “a” 打开文件,而不是 “r+” 模式,简化写入操作。
以下是优化后的代码示例:
def readNames(): try: with open('Attendance.csv', 'r') as f: nameList = [line.split(',')[0] for line in f] except FileNotFoundError: # 如果文件不存在,创建一个空文件并返回一个空列表 open('Attendance.csv', 'w').close() nameList = [] return nameListdef markAttendance(name, nameList): if name not in nameList: nameList.append(name) with open('Attendance.csv', 'a') as f: dt = datetime.now().strftime('%H:%M:%S') f.writelines(f'n{name},{dt}')# --- 主程序 ---nameList = readNames() # 在程序启动时读取姓名列表cap = cv2.VideoCapture(0)while True: # ... (人脸识别代码) ... for encodeFace, faceLoc in zip(encodesCurFrame, facesCurFrame): matches = face_recognition.compare_faces(encodeListKnown, encodeFace) faceDis = face_recognition.face_distance(encodeListKnown, encodeFace) matchIndex = np.argmin(faceDis) if matches[matchIndex]: name = classNames[matchIndex].upper() # ... (绘制矩形框和文字) ... markAttendance(name, nameList) # 传递 nameList
代码解释:
readNames() 函数: 在程序启动时调用,读取 CSV 文件中的所有姓名,并将其存储在 nameList 列表中。增加了异常处理,如果文件不存在则创建。markAttendance() 函数: 接收 nameList 作为参数,直接在内存中进行姓名检查,并将新的姓名添加到 nameList 中。使用 “a” 模式打开文件,进行追加写入。主程序: 在主循环中,将 nameList 传递给 markAttendance() 函数。
注意事项
确保 CSV 文件存在,并且具有正确的格式(姓名,时间)。如果文件不存在,readNames() 函数会创建一个空文件。根据实际情况调整人脸识别的灵敏度,避免误识别导致错误的考勤记录。可以考虑使用数据库存储考勤数据,以便进行更复杂的查询和分析。
总结
通过在写入 CSV 文件之前进行姓名检查,可以有效地避免重复写入考勤记录。通过在程序启动时读取姓名列表,并将其存储在内存中,可以提高程序的效率。根据实际情况选择合适的优化方案,可以构建一个稳定、高效的人脸识别考勤系统。
以上就是解决人脸识别考勤系统重复写入CSV文件的问题的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1378009.html
微信扫一扫
支付宝扫一扫