程序实现一直尝试打开摄像头, 更新自启脚本

This commit is contained in:
haotian 2025-09-30 17:03:22 +08:00
parent 424f6582ba
commit e828deb33b
4 changed files with 96 additions and 35 deletions

View File

@ -20,6 +20,7 @@ camera:
width: 1280
height: 720
fps: 30
retry_interval: 2 # 打开摄像头失败后的重试间隔(秒)
# 人脸检测配置
face_detection:

View File

@ -176,16 +176,35 @@ class FaceRecognitionSystem:
def _init_camera(self):
"""初始化摄像头"""
cam_config = self.config['camera']
retry_interval = cam_config.get('retry_interval', 3) # 默认3秒重试
attempt = 0
while True:
attempt += 1
self.logger.info(f"正在尝试打开摄像头 (第{attempt}次尝试)...")
self.camera = cv2.VideoCapture(cam_config['device_id'])
if self.camera.isOpened():
# 设置摄像头参数
self.camera.set(cv2.CAP_PROP_FRAME_WIDTH, cam_config['width'])
self.camera.set(cv2.CAP_PROP_FRAME_HEIGHT, cam_config['height'])
self.camera.set(cv2.CAP_PROP_FPS, cam_config['fps'])
if not self.camera.isOpened():
raise RuntimeError("无法打开摄像头")
# 验证是否能读取帧
ret, frame = self.camera.read()
if ret:
self.logger.info(f"摄像头初始化成功 (设备ID: {cam_config['device_id']})")
return
else:
self.logger.warning("摄像头已打开但无法读取帧")
self.camera.release()
else:
self.logger.warning(f"无法打开摄像头设备 {cam_config['device_id']}")
self.logger.info("摄像头初始化完成")
# 等待后重试
self.logger.info(f"{retry_interval}秒后重试...")
time.sleep(retry_interval)
def assess_frame_quality(self, frame: np.ndarray) -> float:
"""评估帧质量(使用Laplacian方差检测模糊度)"""

View File

@ -1,16 +1,24 @@
[Unit]
Description=My Custom Startup Script
Description=Face Rec GUI Service (system-level)
After=display-manager.service
# 或者 After=gdm.service / lightdm.service根据你系统用的显示管理器
[Service]
Type=simple
User=unitree
# 配置systemd服务允许访问显示
Environment="DISPLAY=:1"
Environment="XAUTHORITY=/home/unitree/.Xauthority"
# 这里确保自己对这个脚本有执行权限。现chmod +x xxxx.sh
WorkingDirectory=/home/unitree/robot_face_rec
ExecStart=/home/unitree/robot_face_rec/start.sh
Restart=on-failure
WorkingDirectory=/home/unitree/
RestartSec=5
TimeoutStartSec=30
StandardOutput=journal
StandardError=journal
# 如果需要,你可以设置环境,但脚本里会重写 DISPLAY
# Environment=DISPLAY=:0
# Environment=XAUTHORITY=/home/unitree/.Xauthority
[Install]
WantedBy=multi-user.target
WantedBy=graphical.target

View File

@ -1,29 +1,62 @@
#!/bin/bash
# --- 日志相关 ---
LOG_DIR="/home/unitree/robot_face_rec/logs/face_rec"
mkdir -p "$LOG_DIR"
LOG_FILE="$LOG_DIR/face_rec_$(date +%Y%m%d_%H%M%S).log"
# 进入到项目目录
cd /home/unitree/robot_face_rec
{
echo "===== $(date) Starting face_rec script ====="
echo "User: $(whoami)"
echo "PWD before cd: $(pwd)"
echo "Python: $(which python) / Version: $(python --version 2>&1)"
} >> "$LOG_FILE"
LOG_DIR="logs/face_rec"
mkdir -p $LOG_DIR
# 生成日志文件名(使用当前时间)
LOG_FILE="$LOG_DIR/robot_$(date +%Y%m%d_%H%M%S).log"
# 检查当前程序是否已经正在运行.
if pgrep -f "face_rec.py" > /dev/null; then
echo "face_rec.py 已经在运行中"
# 切换到项目目录
cd /home/unitree/robot_face_rec || {
echo "Failed to cd to project dir" >> "$LOG_FILE"
exit 1
}
{
echo "PWD after cd: $(pwd)"
echo "Env before display detection: DISPLAY=$DISPLAY, XAUTHORITY=$XAUTHORITY"
} >> "$LOG_FILE"
# --- 动态检测 DISPLAY 的逻辑 ---
# 方法:尝试从正在运行的 Xorg / X 进程环境中读取 DISPLAY
display_found=""
for pid in $(pgrep Xorg); do
if [ -r /proc/$pid/environ ]; then
disp=$(tr '\0' '\n' < /proc/$pid/environ | grep '^DISPLAY=' | cut -d'=' -f2-)
if [ -n "$disp" ]; then
# display_found="$disp"
echo "Chosen "
break
fi
fi
done
# 如果还没找到 DISPLAY则尝试 fallback
if [ -z "$display_found" ]; then
# 常见默认::0
display_found=":0"
echo "Chosen default"
fi
# nohup python run_sync_robot.py > "$LOG_FILE" 2>&1 &
# 注systemctl控制时最后的&要去掉,使得脚本一直在运行.脚本其实阻塞在这,后面都不会执行
nohup python face_rec.py > "$LOG_FILE" 2>&1
export DISPLAY="$display_found"
# 保存进程id
echo $! > "$LOG_DIR/robot.pid"
echo "WebSocket客户端已启动日志保存在: $LOG_FILE"
echo "进程ID: $(cat $LOG_DIR/robot.pid)"
{
echo "Chosen DISPLAY = $DISPLAY"
} >> "$LOG_FILE"
# XAUTHORITY假设用户的 .Xauthority 存在于 home 目录
export XAUTHORITY="/home/unitree/.Xauthority"
{
echo "Using XAUTHORITY = $XAUTHORITY"
} >> "$LOG_FILE"
# 最终执行 Python 程序(不后台化,用 exec 替换进程)
exec python face_rec.py >> "$LOG_FILE" 2>&1