You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

车载摄像头遮挡检测Python OpenCV算法求助:现有帧差法代码运行异常

车载摄像头遮挡检测代码问题修复方案

原代码核心问题

  • 初始帧逻辑错误:第一次循环cnt=0仅做了cnt自增,没有初始化background为第一帧的灰度均值,导致第一次计算差分是和全黑数组做差,结果完全不符合预期
  • 背景更新逻辑不合理:每10帧强制更新背景,要是遮挡刚好发生在更新节点附近,背景会直接把遮挡后的画面当成新背景,永远无法检测到遮挡
  • 缺失遮挡判定逻辑:仅完成了差分和阈值处理,没有统计差异区域占比、判定是否触发遮挡的步骤
  • 数据类型不匹配:mean_frame是float64类型,直接和uint8类型的背景做差会出现精度问题,阈值判定结果也会受影响
  • 硬编码背景分辨率:写死了背景尺寸为(480,640),如果摄像头实际分辨率不匹配会直接报错

修复后的实现逻辑

  1. 初始化阶段取前N帧无遮挡画面做平均生成初始基准背景,避免单帧噪声干扰
  2. 差分计算后统计阈值化后差异像素的占比,超过设定阈值即判定为遮挡
  3. 仅在确认无遮挡的时候才缓慢更新背景,避免遮挡画面污染基准背景
  4. 统一所有图像的数据类型为uint8,保证计算准确性

修复后可运行代码

import cv2
import numpy as np

def detectCameraBlockage_absdiff():
    cnt = 0
    cap = cv2.VideoCapture(0)
    # 读取摄像头实际分辨率,避免硬编码不匹配
    IMAGE_WIDTH = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
    IMAGE_HEIGHT = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
    # 遮挡判定阈值:差异像素占总像素的比例,可根据实际场景调整
    BLOCKAGE_THRESHOLD_RATIO = 0.3
    # 用于初始背景累积的帧数
    INIT_FRAME_COUNT = 10
    background_accum = np.zeros((IMAGE_HEIGHT, IMAGE_WIDTH), dtype=np.float32)
    background = None
    is_blocked = False

    while True:
        ret, frame = cap.read()
        if not ret:
            print('camera failed.')
            break
        
        # 转灰度均值,统一数据类型为uint8
        mean_frame = frame.mean(axis=2).astype(np.uint8)

        # 初始阶段累积无遮挡背景
        if cnt < INIT_FRAME_COUNT:
            background_accum += mean_frame
            cnt += 1
            # 累积完成后计算初始背景
            if cnt == INIT_FRAME_COUNT:
                background = (background_accum / INIT_FRAME_COUNT).astype(np.uint8)
            # 初始阶段提示
            cv2.putText(frame, "Initializing background...", (20, 30), 
                        cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
        else:
            # 计算差分并二值化
            diff = cv2.absdiff(background, mean_frame)
            _, diff_bin = cv2.threshold(diff, 30, 255, cv2.THRESH_BINARY)
            # 统计差异像素占比
            diff_ratio = np.count_nonzero(diff_bin) / (IMAGE_WIDTH * IMAGE_HEIGHT)

            # 判定是否遮挡
            if diff_ratio > BLOCKAGE_THRESHOLD_RATIO:
                is_blocked = True
                cv2.putText(frame, "CAMERA BLOCKED!", (20, 30), 
                            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 255), 2)
            else:
                is_blocked = False
                cv2.putText(frame, "Normal", (20, 30), 
                            cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 255, 0), 2)
                # 无遮挡时才缓慢更新背景,适配光线缓慢变化的车载场景
                background = cv2.addWeighted(background, 0.95, mean_frame, 0.05, 0)

            cv2.imshow('diff', diff_bin)
        
        cv2.imshow('if you want to quit press the key [q]', frame)
        if cv2.waitKey(1) == ord('q'):
            break
    
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    detectCameraBlockage_absdiff()

参数调整说明

  • 二值化阈值30:可根据实际场景的光线情况调整,暗光场景可适当调低,强光场景可适当调高
  • BLOCKAGE_THRESHOLD_RATIO:遮挡判定的面积比例,需要检测小面积遮挡可调低到0.1左右,仅检测大面积遮挡可调高到0.4以上
  • 背景更新权重0.95和0.05:背景权重越接近1,背景更新速度越慢,抗干扰能力越强,可根据车载场景的光线变化速度调整

内容的提问来源于stack exchange,提问作者Jue

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 12:15:00