假如我希望给公司门口的摄像头做个人脸打卡程序,自动录入扫描到的人脸,自动分析人脸所对应的人并保存出入记录。在没有进行登记前保存记录为用户n,当登记后自动将数据改为对应用户。视频地址为http://192.168.16.153/live/test.flv。使用opencv实现。后端使用json保存数据不使用数据库,用户人脸图片保存在单独的文件夹并以用户名+时间戳命名。请给我完整的代码,包含识别录入的程序,用户登记绑定的程序,简单的本地运行的后端服务。并给我推荐的python版本以及在conda上面install上面所需python依赖的代码
时间: 2025-06-23 21:20:22 浏览: 9
<think>好的,我需要帮用户实现一个基于OpenCV的人脸打卡系统。首先,用户的需求是公司门口摄像头的人脸识别,自动记录未注册用户为“用户n”,注册后关联到具体用户。后端用JSON存储数据,图片按用户名+时间戳保存。需要提供完整代码,包括识别、注册、后端服务,还有Python版本和依赖安装说明。
首先,我应该考虑整个系统的结构。可能需要分成几个部分:人脸检测与识别、用户注册绑定、数据存储和API服务。用户提到的视频流地址是HTTP的,所以要用OpenCV读取视频流。可能需要使用face_recognition库,因为它基于dlib,准确度不错,适合人脸识别。
接下来,数据存储用JSON,所以需要处理读写JSON文件的操作。图片保存路径要检查是否存在,不存在则创建。文件名格式是用户名加时间戳,要注意时间戳的生成和格式化。
用户注册部分需要单独的程序,可能通过命令行输入用户名,然后捕获图像并提取人脸编码,保存到JSON中。同时需要处理当用户未注册时,保存为“用户n”,注册后更新记录。
关于依赖,face_recognition库需要dlib,可能安装比较麻烦,特别是Windows用户。需要提醒用户安装CMake和Visual Studio构建工具。Python版本建议3.8以上,兼容性较好。
代码结构方面,主程序循环读取视频流,检测人脸,与已知编码比对。如果未识别,保存为未知用户,并生成临时ID。注册程序则单独运行,输入用户名后拍照,提取编码并添加到JSON文件中。
后端服务可能需要一个简单的FastAPI应用,提供添加用户和查询记录的接口。虽然用户说不使用数据库,但用JSON文件模拟数据库操作,需要注意线程安全和文件锁的问题,但简单情况下可能忽略,因为并发可能不高。
测试时需要注意摄像头是否可访问,视频流地址是否正确。另外,人脸识别的准确度受光照、角度影响,可能需要用户调整摄像头位置或增加多角度录入。
最后,整理代码,确保各部分功能分离,比如人脸处理、数据存储、API服务分开。提供conda安装命令,包括opencv、face_recognition、fastapi等库。提醒用户安装时的可能问题,比如dlib的编译依赖。
可能遇到的问题:视频流无法打开,需要检查OpenCV的VideoCapture是否正确处理HTTP流;人脸检测失败时如何处理;JSON文件的读写冲突。需要加入异常处理,比如重试读取或文件锁机制,但简单实现可能暂时忽略这些。
总结步骤:
1. 安装依赖,确认环境。
2. 编写人脸检测和识别的主程序,处理实时视频流。
3. 编写注册程序,绑定用户和人脸编码。
4. 编写FastAPI后端服务,提供API接口。
5. 测试各模块是否正常工作,确保数据正确保存和更新。</think>我将分步骤为您构建这个系统,以下是详细实现方案:
环境准备 (Python 3.8+推荐)
```bash
conda create -n face_attendance python=3.8
conda activate face_attendance
conda install -c conda-forge cmake # dlib编译依赖
pip install opencv-python face-recognition fastapi uvicorn python-multipart
```
目录结构
```
├── api.py # 后端服务
├── face_service.py # 主识别程序
├── register.py # 用户注册程序
├── data
│ ├── faces.json # 用户数据存储
│ └── face_images # 人脸图片存储
```
1. 主识别程序 (face_service.py)
```python
import os
import json
import cv2
import face_recognition
from datetime import datetime
# 初始化配置
VIDEO_URL = "http://192.168.16.153/live/test.flv"
DATA_FILE = "data/faces.json"
IMG_DIR = "data/face_images"
UNKNOWN_PREFIX = "用户"
def load_known_faces():
if not os.path.exists(DATA_FILE):
return {"users": []}
with open(DATA_FILE) as f:
return json.load(f)
def save_unknown_face(image, user_id):
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
filename = f"{UNKNOWN_PREFIX}{user_id}_{timestamp}.jpg"
cv2.imwrite(os.path.join(IMG_DIR, filename), image)
def main():
known_data = load_known_faces()
video_capture = cv2.VideoCapture(VIDEO_URL)
unknown_counter = 1
while True:
ret, frame = video_capture.read()
if not ret:
continue
rgb_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
face_locations = face_recognition.face_locations(rgb_frame)
face_encodings = face_recognition.face_encodings(rgb_frame, face_locations)
for (top, right, bottom, left), face_encoding in zip(face_locations, face_encodings):
match = None
for user in known_data["users"]:
stored_enc = [float(x) for x in user["encoding"]]
if face_recognition.compare_faces([stored_enc], face_encoding)[0]:
match = user["username"]
break
if match:
label = f"用户: {match}"
else:
label = f"{UNKNOWN_PREFIX}{unknown_counter}"
save_unknown_face(frame, unknown_counter)
unknown_counter += 1
cv2.rectangle(frame, (left, top), (right, bottom), (0, 0, 255), 2)
cv2.putText(frame, label, (left + 6, bottom - 6),
cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 255, 255), 1)
cv2.imshow('Face Attendance', frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
video_capture.release()
cv2.destroyAllWindows()
if __name__ == "__main__":
if not os.path.exists(IMG_DIR):
os.makedirs(IMG_DIR)
main()
```
2. 用户注册程序 (register.py)
```python
import cv2
import face_recognition
import json
import os
DATA_FILE = "data/faces.json"
def register_user():
username = input("请输入用户名:").strip()
cap = cv2.VideoCapture(0)
print("正在捕获人脸...")
while True:
ret, frame = cap.read()
rgb_frame = cv2.cvtColor(frame, cv2.FONT_HERSHEY_SIMPLEX)
face_locations = face_recognition.face_locations(rgb_frame)
if len(face_locations) == 1:
encoding = face_recognition.face_encodings(rgb_frame, face_locations)[0]
cap.release()
cv2.destroyAllWindows()
break
elif len(face_locations) > 1:
print("检测到多张人脸,请保持单人录入!")
else:
print("未检测到人脸,请正对摄像头...")
# 更新数据
if os.path.exists(DATA_FILE):
with open(DATA_FILE) as f:
data = json.load(f)
else:
data = {"users": []}
data["users"].append({
"username": username,
"encoding": [float(x) for x in encoding]
})
with open(DATA_FILE, 'w') as f:
json.dump(data, f, indent=2)
print(f"用户 {username} 注册成功!")
if __name__ == "__main__":
register_user()
```
3. 后端服务 (api.py)
```python
from fastapi import FastAPI, UploadFile
from fastapi.responses import JSONResponse
import json
import os
import uuid
from datetime import datetime
app = FastAPI()
DATA_FILE = "data/faces.json"
IMG_DIR = "data/face_images"
@app.post("/register")
async def register_user(username: str, file: UploadFile):
# 保存图片
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
filename = f"{username}_{timestamp}.jpg"
file_path = os.path.join(IMG_DIR, filename)
with open(file_path, "wb") as f:
f.write(await file.read())
return JSONResponse({"status": "success", "filename": filename})
@app.get("/records")
async def get_records():
if not os.path.exists(DATA_FILE):
return []
with open(DATA_FILE) as f:
return json.load(f)
if __name__ == "__main__":
import uvicorn
uvicorn.run(app, host="0.0.0.0", port=8000)
```
运行说明:
1. 启动API服务:`python api.py`
2. 运行主程序:`python face_service.py`
3. 注册用户:`python register.py`
系统工作流程:
1. 主程序持续扫描视频流中的人脸
2. 未注册人脸会自动保存为"用户n"并记录时间戳
3. 运行注册程序录入正式用户信息
4. API提供数据查询和远程注册接口
优化建议:
1. 可增加人脸质量检测(睁眼检测、姿态检测)
2. 添加定期清理过期临时记录的脚本
3. 使用JWT保护API接口
4. 增加人脸识别置信度阈值控制
5. 使用多线程处理视频流和人脸识别
注意:实际部署时需确保摄像头RTSP/HTTP流可访问,建议先使用本地摄像头测试(将VIDEO_URL改为0)
阅读全文
相关推荐















