自适应背景构造方法——视频帧差CDM(Change Detection Mask)

本文介绍视频帧差CDM算法,其目的是从视频序列中提取背景图片,可用于获取前景图。算法原理基于监控画面背景短时间光影变化小,通过公式构造背景。使用Python和OpenCV实现,用UCSD Pedestrian Dataset测试,但存在阈值需人工调参的弊端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

由于是第一次写博客,所以难免有错误遗漏,又因为在监控毕业设计中用了这个算法,还挺好用的,所以就打算写一下,如果有错误还请大家指出XD

1 视频帧差CDM介绍

1.1 算法目的

  对于该算法目的简单解释就是在基于已有的视频序列下,经过该算法处理,得到该视频序列中的背景图片(即长时间无移动物体的图像),同时可以使用该算法来获得视频或者一系列图像中的背景图像,然后利用背景处理其他数据,如获得人群前景图以及其他在图像中移动的物体前景图。

1.2 算法原理

  视频帧差CDM算法原理比较简单理解和易于实现。根据监控画面的背景在短时间内不会有较大的光影变化,适用视频帧差法CDM的方法来构造背景图像。构造此背景的方法的前提为人物在背景是时刻处于移动,图像的整体的背景总是能出现应有细节,即背景能从一系列的图像后表现出来,方法的原理如下[1-2]
  假设图像序列的亮度分量为Ii (x,y),其中x,y表示像素位置,i表示帧数 (i=1,…,N) , N为序列帧的总数,用以下公式来表示:
C D M i ( x , y ) = { d , d ≥ T 0 , d &lt; T CDM_{i}(x,y)=\left\{ \begin{aligned} d,d \geq T\\ 0,d&lt;T \end{aligned} \right. CDMi(x,y)={d,dT0,d<T
I i + 1 ( x , y ) − I i ( x , y ) I_{i+1}(x,y)-I_{i}(x,y) Ii+1(x,y)Ii(x,y)
  其中阈值T用来控制去除噪声。对于位置(x,y),CDMi (x,y)表示了在位置(x,y)像素变化的曲线。根据 CDMi (x,y) 是否大于零来进行曲线分段,并将其中被检测到的静止部分用集合{Sj (x,y),1≤j≤M}表示,像素曲线如下图所示:
图像像素曲线变化图
  其中, Sj的起点和终点分别是 STj和 ENj。在位置(x,y)对应的{Sj}的集合中,选择最长的静止段再得到该分段中点对应的帧号 M(x,y)。第 M(x,y)帧的点用来填充图像中相应位置,用公式来表示:
M ( x , y ) = ( S T ( x , y ) + E N ( x , y ) ) / 2 M(x,y)=(ST(x,y)+EN(x,y))/2 M(x,y)=(ST(x,y)+EN(x,y))/2
B ( x , y ) = I ( x , y , M ( x , y ) ) B(x,y)=I(x,y,M(x,y)) B(x,y)=I(x,y,M(x,y))
  其中 ST(x,y)和 EN(x,y)是对应最长静止段的起点以及终点,B(x,y)为重建的背景,这种方法可以恢复相对完整背景图。

2 视频帧差CDM实现

2.1 算法实现

  我使用了python3进行算法的实现,使用openCV3进行像素值的处理,由于算法代码为初始版本,时间复杂度为O(NML)(N,M为图像分辨率,L为图像数量),仅为参考:

# -*- coding: utf-8 -*-
"""
Created on Sat Mar  9 13:39:04 2019

@author: APone
"""
# -*- coding: utf-8 -*-
import cv2 as cv
import numpy as np

# 构造背景
def build_background(images, N, T):
    height = images[0].shape[0]
    width = images[0].shape[1]
    s = np.zeros([height, width, 2])

    for y in range(height):
        for x in range(width):
            flag = False
            start = 1
            end = 1
            for n in range(1, N - 1):
            	#获得前后帧的像素点差分的值d
                d = abs(int(images[n][y, x]) - int(images[n - 1][y, x]))
                #加入差分值小于阈值T,取值为0,否则保留
                if d < T:
                    result = 0
                else:
                    result = d
				#记录单个像素的在整个序列过程中处于“0”平稳的最长分段(即S),
                if result == 0 and flag is False:
                    start = n
                    flag = True
                elif result != 0 and flag is True:
                    end = n
                    flag = False
                    temp = int(s[y][x][1] - s[y][x][0])
                    if (end - start) > temp:
                    	#记录前后帧标记
                        s[y][x][0] = start
                        s[y][x][1] = end

    background = images[0].copy()
    for y in range(height):
        for x in range(width):
        	#将记录的最长分段的前后帧的标记取中间帧号,最后从帧序列中找出该帧并获取该像素点的像素值
            median = int((s[y, x][0] + s[y, x][1]) / 2)
            background[y][x] = images[median][y][x]

    return background


# 使用背景和图像进行差分提取前景图
def background_diff(background, images):
    c_frame = cv.absdiff(images, background)
    return c_frame


# 图像的预处理,使用中值滤波和加权平均灰度化
def images_pretreatment(images, T):
    images = cv.cvtColor(images, cv.COLOR_BGR2GRAY)
    images = cv.medianBlur(images, T)
    return images

2.2 算法效果

  人群图像序列我使用了UCSD Pedestrian Dataset,里面包括了拍摄的两种不同的人群图像序列。可以从以下网址来获取数据集,如果要使用到论文中,请注明引用:
UCSD Pedestrian Dataset

(1)图像数据集展示:
人群图像序列
(2)使用CDM算法处理后获得的背景图像:


图像1
图像2

3 后记

  这个初始算法的一个弊端是有关于像素差分的判断阈值T仍然是由人工调参,不能保证适应所有情况,比如可能用到其他的图像会出现污点的情况等,最佳的理想状态是算法利用额外的统计算法进行阈值自我调整,这个问题还需待改进。

4 相关引用

[1] 唐勇, 姜昱明. 一种基于彩色图像的运动人体分割方法[J]. 微电子学与计算机, 2006, 23(03): 70-72.
[2] 邓玉春,姜昱明. 动态场景中的背景恢复[J]. 微电子学与计算机, 2004, 21(11): 70-72.

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值