目标跟踪指的是对视频中的移动目标进行定位的过程。


在如今AI行业有着很多应用场景,比如监控,辅助驾驶等。


对于如何实现视频的目标跟踪,也有着许多方法。


比如跟踪所有移动目标时,视频每帧之间的变化就显得很有用。


如若视频背景不变,即可利用背景变化实现目标跟踪。


还有之前我们实现过的「跳一跳」小游戏。


其中的模板匹配,也是一种目标跟踪方法,能够很好的跟踪到小跳人的位置。



接下来看一下一些简单的目标跟踪案例。



/ 01 / 帧之间差异


下面就通过计算视频帧之间的差异(即考虑背景帧和其他帧之间的差异),进而实现目标跟踪。


具体代码如下。


import cv2

# 获取视频
video = cv2.VideoCapture('007.mp4')

# 生成椭圆结构元素
es = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (94))
# 设置背景帧
background = None

while True:
    # 读取视频每一帧
    ret, frame = video.read()

    # 获取背景帧
    if background is None:
        # 将视频的第一帧图像转为灰度图
        background = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        # 对灰度图进行高斯模糊,平滑图像
        background = cv2.GaussianBlur(background, (2121), 0)
        continue

    # 将视频的每一帧图像转为灰度图
    gray_frame = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # 对灰度图进行高斯模糊,平滑图像
    gray_frame = cv2.GaussianBlur(gray_frame, (2121), 0)

    # 获取当前帧与背景帧之间的图像差异,得到差分图
    diff = cv2.absdiff(background, gray_frame)

    # 利用像素点值进行阈值分割,得到一副黑白图像
    diff = cv2.threshold(diff, 25255, cv2.THRESH_BINARY)[1]

    # 膨胀图像,减少错误
    diff = cv2.dilate(diff, es, iterations=2)

    # 得到图像中的目标轮廓
    image, cnts, hierarchy = cv2.findContours(diff.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for c in cnts:
        if cv2.contourArea(c) < 1500:
            continue
        # 绘制目标矩形框
        (x, y, w, h) = cv2.boundingRect(c)
        cv2.rectangle(frame, (x+2, y+2), (x+w, y+h), (02550), 2)

    # 显示检测视频
    cv2.namedWindow('contours'0)
    cv2.resizeWindow('contours'600400)
    cv2.imshow('contours', frame)

    # 显示差异视频
    cv2.namedWindow('diff'0)
    cv2.resizeWindow('diff'600400)
    cv2.imshow('diff', diff)
    if cv2.waitKey(1) & 0xff == ord('q'):
        break

# 结束
cv2.destroyAllWindows()
video.release()


得到的视频结果如下。


https://v.qq.com/x/page/a08960zo3yk.html


就这个视频来看,效果还不错。


每次的变化都跟踪出来了。


不过这种方法还是存在缺陷的,因为真正的应用场景下,视频背景不可能那么完美。


必然会受到环境的影响,比如光照的变化。


这将极大影响视频的背景。



/ 02 / 背景分割器


OpenCV提供一个BackgroundSubtractor的类,可以用于分割视频的前景和背景。


还可以通过机器学习提高背景检测的效果。


有三种背景分割器,分别是KNN,MOG2,GMG,通过相应的算法计算背景分割。


BackgroundSubtractor类可以对不同帧进行比较,并存储以前的帧,可按时间推移来提高运动分析的结果。


还能计算阴影,通过检测阴影,排除检测图像的阴影区域。


下面通过一个实例来演示一下,代码如下。


import cv2

# 获取视频
video = cv2.VideoCapture('traffic.flv')
# KNN背景分割器,设置阴影检测
bs = cv2.createBackgroundSubtractorKNN(detectShadows=True)

while True:
    # 读取视频每一帧
    ret, frame = video.read()
    # 计算视频的前景掩码
    fgmask = bs.apply(frame)
    # 图像阈值化
    th = cv2.threshold(fgmask.copy(), 244255, cv2.THRESH_BINARY)[1]
    # 膨胀图像,减少错误
    dilated = cv2.dilate(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (33)), iterations=2)

    # 得到图像中的目标轮廓
    image, contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

    for c in contours:
        if cv2.contourArea(c) > 1600:
            # 绘制目标矩形框
            (x, y, w, h) = cv2.boundingRect(c)
            cv2.rectangle(frame, (x, y), (x+w, y+h), (2552550), 2)

    # 显示差异视频
    cv2.imshow('mog', fgmask)
    # cv2.imshow('thresh', th)
    # 显示检测视频
    cv2.imshow('detection', frame)
    if cv2.waitKey(30) & 0xff == ord('q'):
        break

video.release()
cv2.destroyAllWindows()


得到结果如下。


https://v.qq.com/x/page/e08964j2ddi.html


效果也还不错。



/ 03 / 总结


相关视频及代码已上传网盘,公众号回复「目标跟踪」即可获取。


对于目标跟踪,还有很多方法,比如均值漂移、CAMShift、卡尔曼滤波器等。


本次就先马克这些,其余的以后慢慢了解~


万水千山总是情,点个「在看」行不行。

···  END  ···

©著作权归作者所有:来自51CTO博客作者mb5fe18ec4a4df8的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 你知道Jupyter notebook还可以用来做 “视频聊天室” 吗?
  2. 用数据分析大家最喜欢什么类型的抖音视频。
  3. 用Python生成抖音字符视频!
  4. 用Python清除文件夹中的重复视频
  5. 用Python全自动下载抖音视频!
  6. 教你使用Python下载全网视频
  7. 视频当道的时代,这些珍藏的优质 Python 播客值得推荐
  8. 20张图!3个视频!一文带你搞定「快慢指针」在数组中的应用
  9. 以B站C语言视频为基础的课后总结(一)

随机推荐

  1. golang context用来干吗
  2. 在go modules里使用go get进行包管理的介
  3. Go生成go动态库或静态库的方法
  4. golang channel有什么好处
  5. golang channel是什么
  6. go中的数据结构-字典map详解
  7. Golang Cgo是什么
  8. go中的数据结构-接口interface(详解)
  9. go defer(go延迟函数)介绍
  10. golang cap是什么意思