feat: 视觉记录系统 v1.0.0 - 摄像头定时拍照+智能分析+Web界面

This commit is contained in:
2026-04-16 09:42:53 +08:00
commit 49785191c3
14 changed files with 1997 additions and 0 deletions

118
camera.py Normal file
View File

@@ -0,0 +1,118 @@
"""
摄像头拍照模块 - Windows 兼容
"""
import cv2
import os
import datetime
from pathlib import Path
from config import IMAGES_DIR, CAMERA_INDEX
class CameraCapture:
"""摄像头拍照管理"""
def __init__(self, camera_index=CAMERA_INDEX):
self.camera_index = camera_index
self.cap = None
def open(self):
"""打开摄像头"""
if self.cap is None or not self.cap.isOpened():
self.cap = cv2.VideoCapture(self.camera_index, cv2.CAP_DSHOW) # Windows DirectShow
if not self.cap.isOpened():
raise Exception(f"无法打开摄像头 {self.camera_index}")
# 设置分辨率
self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
return self.cap.isOpened()
def close(self):
"""关闭摄像头"""
if self.cap is not None:
self.cap.release()
self.cap = None
def capture(self, save_path=None):
"""拍照并保存
Returns:
dict: {'success': bool, 'path': str, 'timestamp': str, 'error': str}
"""
try:
self.open()
# 等待摄像头稳定Windows 上需要预热)
for _ in range(5):
self.cap.read()
ret, frame = self.cap.read()
if not ret:
return {'success': False, 'error': '无法捕获图像'}
# 生成文件名
timestamp = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
if save_path is None:
filename = f"capture_{timestamp}.jpg"
save_path = IMAGES_DIR / filename
# 保存图片
cv2.imwrite(str(save_path), frame, [cv2.IMWRITE_JPEG_QUALITY, 90])
return {
'success': True,
'path': str(save_path),
'timestamp': timestamp,
'filename': save_path.name
}
except Exception as e:
return {'success': False, 'error': str(e)}
def get_camera_info(self):
"""获取摄像头信息"""
try:
self.open()
width = int(self.cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(self.cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fps = int(self.cap.get(cv2.CAP_PROP_FPS))
return {
'index': self.camera_index,
'width': width,
'height': height,
'fps': fps,
'status': 'opened'
}
except Exception as e:
return {
'index': self.camera_index,
'status': 'error',
'error': str(e)
}
def __del__(self):
self.close()
def list_available_cameras(max_test=5):
"""列出可用的摄像头"""
available = []
for i in range(max_test):
cap = cv2.VideoCapture(i, cv2.CAP_DSHOW)
if cap.isOpened():
available.append(i)
cap.release()
return available
if __name__ == "__main__":
# 测试摄像头
print("检测可用摄像头...")
cams = list_available_cameras()
print(f"可用摄像头: {cams}")
if cams:
print("\n测试拍照...")
camera = CameraCapture(cams[0])
result = camera.capture()
print(f"结果: {result}")
camera.close()