|
|
|
|
|
|
|
|
|
import cv2 |
|
import json |
|
import logging |
|
import sys |
|
import time |
|
from pathlib import Path |
|
|
|
|
|
project_root = Path(__file__).parent.parent |
|
sys.path.append(str(project_root)) |
|
|
|
|
|
from src.utils.config_manager import ConfigManager |
|
|
|
|
|
logging.basicConfig( |
|
level=logging.INFO, |
|
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' |
|
) |
|
logger = logging.getLogger("CameraScanner") |
|
|
|
|
|
def get_camera_capabilities(cam): |
|
"""获取摄像头的参数和能力""" |
|
capabilities = {} |
|
|
|
|
|
standard_resolutions = [ |
|
(640, 480), |
|
(800, 600), |
|
(1024, 768), |
|
(1280, 720), |
|
(1280, 960), |
|
(1920, 1080), |
|
(2560, 1440), |
|
(3840, 2160) |
|
] |
|
|
|
supported_resolutions = [] |
|
original_width = int(cam.get(cv2.CAP_PROP_FRAME_WIDTH)) |
|
original_height = int(cam.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
|
|
|
|
|
capabilities["default_resolution"] = (original_width, original_height) |
|
|
|
|
|
for width, height in standard_resolutions: |
|
cam.set(cv2.CAP_PROP_FRAME_WIDTH, width) |
|
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, height) |
|
actual_width = int(cam.get(cv2.CAP_PROP_FRAME_WIDTH)) |
|
actual_height = int(cam.get(cv2.CAP_PROP_FRAME_HEIGHT)) |
|
|
|
|
|
if actual_width == width and actual_height == height: |
|
supported_resolutions.append((width, height)) |
|
|
|
|
|
cam.set(cv2.CAP_PROP_FRAME_WIDTH, original_width) |
|
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, original_height) |
|
|
|
capabilities["supported_resolutions"] = supported_resolutions |
|
|
|
|
|
fps = int(cam.get(cv2.CAP_PROP_FPS)) |
|
capabilities["fps"] = fps if fps > 0 else 30 |
|
|
|
|
|
backend_name = cam.getBackendName() |
|
capabilities["backend"] = backend_name |
|
|
|
return capabilities |
|
|
|
|
|
def detect_cameras(): |
|
"""检测并列出所有可用摄像头""" |
|
print("\n===== 摄像头设备检测 =====\n") |
|
|
|
|
|
config_manager = ConfigManager.get_instance() |
|
|
|
|
|
current_camera_config = config_manager.get_config("CAMERA", {}) |
|
logger.info(f"当前相机配置: {current_camera_config}") |
|
|
|
|
|
camera_devices = [] |
|
|
|
|
|
max_cameras_to_check = 10 |
|
|
|
for i in range(max_cameras_to_check): |
|
try: |
|
|
|
cap = cv2.VideoCapture(i) |
|
|
|
if cap.isOpened(): |
|
|
|
device_name = f"Camera {i}" |
|
try: |
|
|
|
device_name = cap.getBackendName() + f" Camera {i}" |
|
except Exception as e: |
|
logger.warning(f"获取设备{i}名称失败: {e}") |
|
pass |
|
|
|
|
|
ret, frame = cap.read() |
|
if not ret: |
|
print(f"设备 {i}: 打开成功但无法读取画面,跳过") |
|
cap.release() |
|
continue |
|
|
|
|
|
capabilities = get_camera_capabilities(cap) |
|
|
|
|
|
width, height = capabilities['default_resolution'] |
|
resolutions_str = ", ".join( |
|
[f"{w}x{h}" for w, h in capabilities['supported_resolutions']] |
|
) |
|
|
|
print(f"设备 {i}: {device_name}") |
|
print(f" - 默认分辨率: {width}x{height}") |
|
print(f" - 支持分辨率: {resolutions_str}") |
|
print(f" - 帧率: {capabilities['fps']}") |
|
print(f" - 后端: {capabilities['backend']}") |
|
print("") |
|
|
|
|
|
camera_devices.append({ |
|
"index": i, |
|
"name": device_name, |
|
"capabilities": capabilities |
|
}) |
|
|
|
|
|
print(f"正在显示设备 {i} 的预览画面,按 'q' 键继续...") |
|
preview_start = time.time() |
|
|
|
while time.time() - preview_start < 3: |
|
ret, frame = cap.read() |
|
if ret: |
|
cv2.imshow(f'Camera {i} Preview', frame) |
|
if cv2.waitKey(1) & 0xFF == ord('q'): |
|
break |
|
|
|
cv2.destroyAllWindows() |
|
cap.release() |
|
|
|
else: |
|
|
|
consecutive_failures = 0 |
|
for j in range(i, i + 2): |
|
temp_cap = cv2.VideoCapture(j) |
|
if not temp_cap.isOpened(): |
|
consecutive_failures += 1 |
|
temp_cap.release() |
|
|
|
if consecutive_failures >= 2 and i > 0: |
|
break |
|
|
|
except Exception as e: |
|
print(f"检测设备 {i} 时出错: {e}") |
|
|
|
|
|
print("\n===== 设备总结 =====\n") |
|
|
|
if not camera_devices: |
|
print("未找到可用的摄像头设备!") |
|
return None |
|
|
|
print(f"找到 {len(camera_devices)} 个摄像头设备:") |
|
for device in camera_devices: |
|
width, height = device['capabilities']['default_resolution'] |
|
print(f" - 设备 {device['index']}: {device['name']}") |
|
print(f" 分辨率: {width}x{height}") |
|
|
|
|
|
print("\n===== 推荐设备 =====\n") |
|
|
|
|
|
recommended_camera = None |
|
highest_resolution = 0 |
|
|
|
for device in camera_devices: |
|
width, height = device['capabilities']['default_resolution'] |
|
resolution = width * height |
|
|
|
|
|
if width >= 1280 and height >= 720: |
|
if resolution > highest_resolution: |
|
highest_resolution = resolution |
|
recommended_camera = device |
|
elif recommended_camera is None or resolution > highest_resolution: |
|
highest_resolution = resolution |
|
recommended_camera = device |
|
|
|
|
|
if recommended_camera: |
|
r_width, r_height = recommended_camera['capabilities']['default_resolution'] |
|
print(f"推荐摄像头: 设备 {recommended_camera['index']} " |
|
f"({recommended_camera['name']})") |
|
print(f" - 分辨率: {r_width}x{r_height}") |
|
print(f" - 帧率: {recommended_camera['capabilities']['fps']}") |
|
|
|
|
|
vl_url = current_camera_config.get( |
|
"Loacl_VL_url", |
|
"https://open.bigmodel.cn/api/paas/v4/" |
|
) |
|
vl_api_key = current_camera_config.get("VLapi_key", "你自己的key") |
|
model = current_camera_config.get("models", "glm-4v-plus") |
|
|
|
|
|
print("\n===== 配置文件示例 =====\n") |
|
|
|
new_camera_config = { |
|
"camera_index": recommended_camera['index'], |
|
"frame_width": r_width, |
|
"frame_height": r_height, |
|
"fps": recommended_camera['capabilities']['fps'], |
|
"Loacl_VL_url": vl_url, |
|
"VLapi_key": vl_api_key, |
|
"models": model |
|
} |
|
|
|
print(json.dumps(new_camera_config, indent=2, ensure_ascii=False)) |
|
|
|
|
|
print("\n是否要更新配置文件中的摄像头配置?(y/n)") |
|
choice = input().strip().lower() |
|
|
|
if choice == 'y': |
|
try: |
|
|
|
success = config_manager.update_config("CAMERA", new_camera_config) |
|
|
|
if success: |
|
print("\n摄像头配置已成功更新到config.json!") |
|
else: |
|
print("\n更新摄像头配置失败!") |
|
|
|
except Exception as e: |
|
logger.error(f"更新配置时出错: {e}") |
|
print(f"\n更新配置时出错: {e}") |
|
|
|
return camera_devices |
|
|
|
|
|
if __name__ == "__main__": |
|
try: |
|
cameras = detect_cameras() |
|
if cameras: |
|
print(f"\n检测到 {len(cameras)} 个摄像头设备!") |
|
else: |
|
print("\n未检测到可用的摄像头设备!") |
|
except Exception as e: |
|
logger.error(f"检测过程中出错: {e}") |
|
print(f"检测过程中出错: {e}") |