feat: 视觉记录系统 v1.0.0 - 摄像头定时拍照+智能分析+Web界面
This commit is contained in:
118
camera.py
Normal file
118
camera.py
Normal 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()
|
||||
Reference in New Issue
Block a user