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

资讯 2年前
1.33K
运动检测技术(OpenCV 上的代码)

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

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)

混合高斯码

image.png


       原文标题 : 运动检测技术(OpenCV 上的代码)

© 版权声明

相关文章