运动检测技术(OpenCV 上的代码)

点击上方“小白学视觉”,选择加"星标"或“置顶

重磅干货,第一时间送达36dcdca5d84d9890caecd5e84328d693.jpeg

近年来,运动检测技术已成为计算机视觉的重要研究领域之一。视频序列上已经发明了许多方法,其中一些方法比其他方法更好。在本文中,我们将解释并在 OpenCV 上实现一些基本方法。

fbafc1db907f0dbea375c33e777931ee.png

1. 帧差分

帧差分背后的想法非常简单。我们逐像素检查两个视频帧之间的差异。如果有运动,像素值就会发生变化,因此我们将获得运动图。

很简单对吗?但是,由于噪声(例如照明的变化)可能会发生一些像素值变化,为了避免在我们的运动蒙版中捕获噪声,我们应用了一个阈值,该阈值基本上会突出强度方面的大变化并丢弃小的变化。请注意,阈值没有正确的选择,通常是凭经验完成的。

现在我们理解了这个概念,让我们展示一些代码:

frames=[]
MAX_FRAMES = 1000
N = 2
THRESH = 60
ASSIGN_VALUE = 255 #Value to assign the pixel if the threshold is met

cap = cv2.VideoCapture(0)  #Capture using Computer's Webcam
    
for t in range(MAX_FRAMES):
    #Capture frame by frame
    ret, frame = cap.read()
    #Convert frame to grayscale
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY) 
    #Append to list of frames
    frames.append(frame_gray)
    if t >= N:
        #D(N) = || I(t) - I(t+N) || = || I(t-N) - I(t) ||
        diff = cv2.absdiff(frames[t-N], frames[t])
        #Mask Thresholding
        threshold_method = cv2.THRESH_BINARY
        ret, motion_mask = cv2.threshold(diff, THRESH, ASSIGN_VALUE, threshold_method)
        #Display the Motion Mask
        cv2.imshow('Motion Mask', motion_mask)

这种方法具有计算性能,但是它存在两个主要缺点:前景光圈和由帧速率和物体速度引起的重影。

Kameda 和 Minoh 开发的一种解决方案是双重差分,我们在时间 t 和 t-1 以及 t-1 和 t-2 之间的两个帧之间操作阈值差异,然后将它们与逻辑 AND 结合以确保我们始终检测到一个对象而不是它的重影。

帧差分的另一个问题是,当对象停止移动时,它不再被检测到。这显然取决于我们想要完成的任务,但是假设我们想要继续检测移动物体,即使它停止了一段时间。这个问题的一个答案是背景减法技术。

2. 背景减法

背景减法是一种广泛使用的方法,用于检测静态摄像机帧序列中的移动对象。它需要一个参考图像来播放背景(通常在没有对象的情况下获取)。然后我们计算当前帧和背景帧(参考图像)之间的差异。其主要任务是检测通常代表运动物体的前景。

background = None
MAX_FRAMES = 1000
THRESH = 60
ASSIGN_VALUE = 255

cap = cv2.VideoCapture(0)
    
for t in range(MAX_FRAMES):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Convert frame to grayscale
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)      
    if t == 0:
        # Train background with first frame
        background = frame_gray
    else:
        # Background subtraction
        diff = cv2.absdiff(background, frame_gray)
        # Mask thresholding
        ret, motion_mask = cv2.threshold(diff, THRESH, ASSIGN_VALUE, cv2.THRESH_BINARY)
        # Display the motion mask and background
        cv2.imshow('Motion mask', motion_mask)
        cv2.imshow('Background', background)

背景减法代码

如果对象的颜色与背景框不同,这种方法可以获得很好的效果。然而,像帧差分一样,它也有一些主要的缺点。毋庸置疑,它对光照变化和相机运动高度敏感,它还有一个“waking person"问题,这意味着如果背景物体(属于参考图像的物体)移动,则同时检测到真实物体及其重影.

在这种情况下,我们遇到了与帧差分相反的问题:“如果我们想停止检测前景对象并将其吸收到背景中怎么办?”

3. 自适应背景减法

这种方法基本上结合了之前的两种技术,通过引入学习率 λ 来充分利用两者。在每个时间步,我们对传入图像和先前背景的贡献进行加权以构建新背景。

例如,如果我们设置 λ=0.1,则在更新背景帧之前需要 10 帧(换句话说,前景对象将被吸收到背景中)。而对于 λ=0.5,我们有更快的更新(更新前只需要 2 帧)。请注意,选择 λ 没有规则,它是凭经验完成的,因为它取决于我们正在处理的任务和环境。

background = None
MAX_FRAMES = 1000
THRESH = 60
ASSIGN_VALUE = 255
ALPHA = 0.1

def update_background(current_frame, prev_bg, alpha):
    bg = alpha * current_frame + (1 - alpha) * prev_bg
    bg = np.uint8(bg)  
    return bg

cap = cv2.VideoCapture(0)
    
for t in range(MAX_FRAMES):
    # Capture frame-by-frame
    ret, frame = cap.read()
    # Convert frame to grayscale
    frame_gray = cv2.cvtColor(frame, cv2.COLOR_RGB2GRAY)      
    if t == 0:
        # Train background with first frame
        background = frame_gray
    else:
        # Background subtraction
        diff = cv2.absdiff(background, frame_gray)
        # Mask thresholding
        ret, motion_mask = cv2.threshold(diff, THRESH, ASSIGN_VALUE, cv2.THRESH_BINARY)
        # Update background
        background = update_background(frame_gray, background, alpha = ALPHA)
        # Display the motion mask and background
        cv2.imshow('Motion mask', motion_mask)
        cv2.imshow('Background', background)

自适应背景减法代码

4. 高斯混合(MoG)

高斯混合是一种广泛使用的背景建模方法,用于从静态相机中检测运动物体。

简而言之,这种方法首先将每个像素建模为加权高斯的总和,其中权重定义了每个高斯的贡献。拥有多个高斯而不是一个的直觉是一个像素可以代表许多对象(例如雪花和后面的建筑物)。通过使用以前的帧计算颜色直方图,我们可以知道对象可能是背景或前景对象。

例如,当我们得到一个具有大权重和小标准偏差的高斯时,这意味着所描述的对象经常出现并且在帧之间没有变化,因此它可能是背景的一部分。这就是算法的工作原理;每个输入像素都会根据可用模型进行检查。在匹配的情况下,我们更新模型的权重、均值和标准差,如果权重除以标准差很大,我们将像素分类为背景,否则分类为前景。

MAX_FRAMES = 1000
LEARNING_RATE = -1   
fgbg = cv2.createBackgroundSubtractorMOG2()

cap = cv2.VideoCapture(0)

for t in range(MAX_FRAMES):
    # Capture frame-by-frame
    ret, frame = cap.read()
    #Apply MOG 
    motion_mask = fgbg.apply(frame, LEARNING_RATE)
    #Get background
    background = fgbg.getBackgroundImage()
    # Display the motion mask and background
    cv2.imshow('background', background)
    cv2.imshow('Motion Mask', motion_mask)

混合高斯码

Github 存储库:https://github.com/safaabbes/Motion-Detection-Techniques-using-OpenCV

下载1:OpenCV-Contrib扩展模块中文版教程

在「小白学视觉」公众号后台回复:扩展模块中文教程,即可下载全网第一份OpenCV扩展模块教程中文版,涵盖扩展模块安装、SFM算法、立体视觉、目标跟踪、生物视觉、超分辨率处理等二十多章内容。


下载2:Python视觉实战项目52讲
在「小白学视觉」公众号后台回复:Python视觉实战项目,即可下载包括图像分割、口罩检测、车道线检测、车辆计数、添加眼线、车牌识别、字符识别、情绪检测、文本内容提取、面部识别等31个视觉实战项目,助力快速学校计算机视觉。


下载3:OpenCV实战项目20讲
在「小白学视觉」公众号后台回复:OpenCV实战项目20讲,即可下载含有20个基于OpenCV实现20个实战项目,实现OpenCV学习进阶。


交流群

欢迎加入公众号读者群一起和同行交流,目前有SLAM、三维视觉、传感器、自动驾驶、计算摄影、检测、分割、识别、医学影像、GAN、算法竞赛等微信群(以后会逐渐细分),请扫描下面微信号加群,备注:”昵称+学校/公司+研究方向“,例如:”张三 + 上海交大 + 视觉SLAM“。请按照格式备注,否则不予通过。添加成功后会根据研究方向邀请进入相关微信群。请勿在群内发送广告,否则会请出群,谢谢理解~
  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值