Python+OpenCV利用KNN背景分割器进行静态场景行人检测与轨迹跟踪

Python+OpenCV利用KNN背景分割器进行静态场景行人检测与轨迹跟踪,第1张

前言

视频图像中的目标检测与跟踪,是计算机视觉的基础课题,同时具有广泛的应用价值。视觉目标(单目标)跟踪任务就是在给定某视频序列初始帧的目标大小与位置的情况下,预测后续帧中该目标的大小与位置。本篇文章介绍静态场景的目标检测与跟踪。

主要思路

1.使用KNN背景分割器提取前景(即运动的人物)

2.提取出来的前景通过膨胀和腐蚀的 *** 作去除噪声

3.对处理后的前景中的人物提取轮廓和构建最小外接矩形

4.以最小外接矩阵中的中心点作为运动点画出运动轨迹

KNN背景分割器算法原理

算法的基本原理就是对每一帧图像的环境进行学习,从而推断出背景区域。

算法流程可以总结如下,对于图像某个位置的新像素值:

(1)与该像素值历史信息(包括前⼏帧的像素值和像素点是前景还是背景的判断)⽐较,如果像素值之间的差别在指定阈值内,则认为新像素值与该历史信息是匹配的,是“潜在的”⼀类;所有历史信息⽐较完毕后,如果与历史信息匹配的次数超过了设定阈值,那么:(1)新像素点被归为“潜在背景点”(2)如果被匹配的历史信息中属于背景的点个数超过设定阈值,那么新的像素点就被归为背景点

(2)将新像素点根据⼀定规则保存到历史信息中 

参考自:opencv中的BackgroundSubtractorKNN源码解读_Mega_Li的博客-CSDN博客

代码(Python+OpenCV实现)

代码中有详细的注释,因此不展开陈述了。

import numpy as np
import random
import cv2

def main():
    #读取视频
    camera = cv2.VideoCapture("C:/Users/Pei/Desktop/Lab3/static_bg_people.avi")
    # frame_one读进视频中的第一张图片
    ret, frame_one = camera.read()
    # 创建一个mask,方便后续画轨迹
    mask = np.zeros_like(frame_one)# 全0的画板,size和第一帧图像一样
    # KNN背景分割器
    bs = cv2.createBackgroundSubtractorKNN()

    while True:
        grabbed, frame = camera.read()
        if (grabbed is False):
            print("failed to grab frame.")
            break

        fgmask = bs.apply(frame)  # 获得去掉背景后的图
        # 处理帧,通过前景掩模采用膨胀和腐蚀的方法来去除斑点
        th = cv2.threshold(fgmask.copy(), 127, 255, cv2.THRESH_BINARY)[1]
        # cv2.imshow('th',th)
        #腐蚀 *** 作
        erode = cv2.erode(th, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3, 3)), iterations=2)
        # cv2.imshow('erode', erode)
        #膨胀 *** 作
        dilated = cv2.dilate(erode, cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (10, 7)), iterations=2)
        # cv2.imshow('dilated', dilated)
        #使用cv2.findContours提取轮廓方便后续寻找最小外接矩形
        image, contours, hier = cv2.findContours(dilated, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

        #设置current_point对人物的中心点进行存储,以进行后续的轨迹跟踪
        current_point = np.zeros([0, 2])

        for c in contours:
            # 对轮廓设置最小区域,这里设置500,若设置过小噪声区域也可能识别进去
            if cv2.contourArea(c) > 500:
                (x, y, w, h) = cv2.boundingRect(c)
                cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 1)#画最小外接矩形
                centers = ((2 * x + w) / 2, (2 * y + h) / 2)#矩形的中心点
                current_point = np.insert(current_point, 0, [centers[0], centers[1]], axis=0)

        #画运动轨迹
        for i in current_point:
            a, b = int(i[0]), int(i[1])
            #颜色设置为随机颜色random.randint(0, 255)
            mask = cv2.circle(mask, (a, b), 3,
                              (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)), -1)
        #将视频和mask的内容相结合,显示轨迹,mask需放在while循环外面,否则视频每播放一帧就会进行刷新
        frame = cv2.add(frame, mask)

        cv2.imshow("demo", frame)  # 窗口显示结果
        #按Esc退出
        if cv2.waitKey(110) & 0xff == 27:
            break
    #释放camera
    camera.release()

if __name__ == "__main__":
    main()
效果

 左上角的图是原始的前景图,右上角的图是经过腐蚀 *** 作后的前景图,右下角四经过膨胀后的前景图,左下角是最终的效果图。下面是动态效果图

源视频下载:

链接:https://pan.baidu.com/s/1vJJRU9bjgNR1vpnuq-NsNg 
提取码:1234

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/716077.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-04-25
下一篇 2022-04-25

发表评论

登录后才能评论

评论列表(0条)

保存