视频图像中的目标检测与跟踪,是计算机视觉的基础课题,同时具有广泛的应用价值。视觉目标(单目标)跟踪任务就是在给定某视频序列初始帧的目标大小与位置的情况下,预测后续帧中该目标的大小与位置。本篇文章介绍静态场景的目标检测与跟踪。
主要思路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
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)