首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >目标跟踪与定位——Introduction to motion

目标跟踪与定位——Introduction to motion

作者头像
小飞侠xp
发布2018-10-12 10:02:55
1.1K0
发布2018-10-12 10:02:55
举报

要随着时间变化来跟踪物体并检测动作: 方法之一是提取特定的特征 观察这些特征是怎么从一帧变化到下一帧的,这里可以用到光流法(optical flow)。

光流法

光流法在诸多跟踪和动作分析应用中都有所涉及,其工作原理是通过假设图像帧的两点来实现的:一是物体像素强度在连续的图像帧里没有变化;二是相邻像素具有相同的动作。

光流法会观察兴趣点:如角点或特别明亮的像素,对这些点进行逐帧跟踪。 跟踪一个点或一组点能让我们知道点或物体移动的速度和方向,有了这些数据你就能预测物体接下来会往哪里移动。 所以你可以用光流法来做一些事情,如手势识别或跟踪特定物体 如人或车辆。

光流法原理:

我们使用一个例子来说明: 假设两个来自同一视频的图像帧,对于图像1中的对象上的一个点,想知道在图像2上的什么位置,找到后,我们可以计算动作向量:用以描述这个点从第一帧到第二帧的速度。

  1. 第一个图像中的点(x,y)将以一定的量从这个帧移动到下一帧,水平移动距离为u,垂直移动距离为v
  2. 因此在第二个图像中,该点的坐标降为(x+u,y+v)。
  3. 这个动作可以用动作向量(u,v)表示,向量有大小和方向。假设点向右移动3个像素,向上移动4个像素。则第二帧图像中将为(x+3,y+4)。动作向量为(3,4)。
亮度恒定假设

光流法假设一个图像帧中点与下一个图像帧的相同点具有一样的强度像素值,即光流法假定表面的颜色一直保持不变。在实际情况下这不是完美的假定,但是大部分情况下都很接近事实。 在第一个图像中的点(x,y)强度与图像2中的点(x+u,y+v)强度一样。

到目前为止,我们将这两个点当做(x,y)空间里的两组不同的图像,但是它们在时间上是相关联的。 可以用另一种方式看待这些图像帧: 第一个图像是在时间t发生的二维强度模式; 第一个图像是在时间t+1发生的二维强度模式。 用这种方式,我们可以将一系列图像帧I看做三维图像,具有(x,y)坐标,每个点像素值,深度为时间。

上图的方程式称为亮度恒定假设,这个函数可以进行泰勒级数展开,将这个强度函数表示为多项式的和。

在上图中,我们将各项计算为强度相对于x,y,t的导数。 可以简化这个展开公式:

结果是一个将动作向量的数值 u 和 v与图像强度在空间和时间内的变化联系起来的方程式。 光流会通过查看相同的点从一个图像帧移动到下一个图像帧的位置来跟踪对象,加载一些pacman人脸的示例帧,并使其向右和向下移动,然后观察光流如何找到描述人脸运动的运动矢量。

  1. 首先,导入资源并读入图像。
import numpy as np
import matplotlib.image as mpimg  # for reading in images
import matplotlib.pyplot as plt
import cv2  # computer vision library
%matplotlib inline

# Read in the image frames
frame_1 = cv2.imread('images/pacman_1.png')
frame_2 = cv2.imread('images/pacman_2.png')
frame_3 = cv2.imread('images/pacman_3.png')

# convert to RGB
frame_1 = cv2.cvtColor(frame_1, cv2.COLOR_BGR2RGB)
frame_2 = cv2.cvtColor(frame_2, cv2.COLOR_BGR2RGB)
frame_3 = cv2.cvtColor(frame_3, cv2.COLOR_BGR2RGB)


# Visualize the individual color channels
f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(20,10))
ax1.set_title('frame 1')
ax1.imshow(frame_1)
ax2.set_title('frame 2')
ax2.imshow(frame_2)
ax3.set_title('frame 3')
ax3.imshow(frame_3)
  1. 寻找跟踪点

在使用光流之前,我们必须给它一组用来跟踪两个图像帧的关键点! 在下面的例子中,我们要用到Shi-Tomasi角点检测器,这个检测器会使用与Harris角点检测器相同的过程来查找构成图像中“角点”的强度模式,只是它添加了一个额外的参数来帮助选择最突出的角点。你可以在 这个文档中阅读有关此检测算法的更多信息。 或者,你也可以选择使用Harris甚至ORB来查找特征点。可以参考以前写的两篇文章

# parameters for ShiTomasi corner detection
feature_params = dict( maxCorners = 10,
                       qualityLevel = 0.2,
                       minDistance = 5,
                       blockSize = 5 )


# convert all frames to grayscale
gray_1 = cv2.cvtColor(frame_1, cv2.COLOR_RGB2GRAY)
gray_2 = cv2.cvtColor(frame_2, cv2.COLOR_RGB2GRAY)
gray_3 = cv2.cvtColor(frame_3, cv2.COLOR_RGB2GRAY)


# Take first frame and find corner points in it
pts_1 = cv2.goodFeaturesToTrack(gray_1, mask = None, **feature_params)

# display the detected points
plt.imshow(frame_1)
for p in pts_1:
    # plot x and y detected points
    plt.plot(p[0][0], p[0][1], 'r.', markersize=15)

# print out the x-y locations of the detected points
print(pts_1)
  1. 执行光流

在你感兴趣的初始图像上检测到关键点之后,就可以使用OpenCV的calcOpticalFlowPyrLK计算此图像帧(第1帧)和下一帧(第2帧)之间的光流。其中,calcOpticalFlowPyrLK可以在这里 查看:它会接收初始图像帧、下一张图像和第一组点,并返回下一帧中检测到的点和一个值,该值表示的是从一帧到下一帧之间的点匹配程度。 参数还包括窗口大小和maxLevels,它们分别表示窗口的大小以及将使用金字塔缩放比例缩放给定图像的级别数。此版本会对匹配点进行迭代搜索,此匹配条件则反映在最后一个参数中。如果使用其他图像,则可能需要更改这些值,但更改的值应适用于提供的示例。

# parameters for lucas kanade optical flow
lk_params = dict( winSize  = (5,5),
                  maxLevel = 2,
                  criteria = (cv2.TERM_CRITERIA_EPS | cv2.TERM_CRITERIA_COUNT, 10, 0.03))


# calculate optical flow between first and second frame
pts_2, match, err = cv2.calcOpticalFlowPyrLK(gray_1, gray_2, pts_1, None, **lk_params)

# Select good matching points between the two image frames
good_new = pts_2[match==1]
good_old = pts_1[match==1]

接下来,让我们把生成的运动矢量显示出来吧!你应该看到第一个图像上绘有运动矢量,该运动矢量表示的是从第一帧到下一帧的运动方向。

# create a mask image for drawing (u,v) vectors on top of the second frame
mask = np.zeros_like(frame_2)

# draw the lines between the matching points (these lines indicate motion vectors)
for i,(new,old) in enumerate(zip(good_new,good_old)):
    a,b = new.ravel()
    c,d = old.ravel()
    # draw points on the mask image
    mask = cv2.circle(mask,(a,b),5,(200),-1)
    # draw motion vector as lines on the mask image
    mask = cv2.line(mask, (a,b),(c,d), (200), 3)
    # add the line image and second frame together

composite_im = np.copy(frame_2)
composite_im[mask!=0] = [0]

plt.imshow(composite_im)

光流法被用于许多跟踪技术中,比如NVIDIA Redtail无人机,它使用光流法跟踪视频流中周围物体

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018.10.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 光流法
    • 亮度恒定假设
    相关产品与服务
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档