阅读 63

opencv 移动侦测,监控的移动追踪

前言

固定监控,需要快速标记全天候出现画面变化的时间段,需要使用到运动侦测的方法,本文主要使用帧差法进行计算。


点跟踪:

这类方法通常在连续帧中检测到的目标被表达为点。再引入其它方法来进行目标检测。其问题可以用帧与帧之间检测到的目标点之间的关系来表达。方法可分为两大类:确定性方法和统计性方法。前者通常用定性的运动限制方法,后者用目标检测和不确定性的建模来建立关联。(1)确定性的方法定义了在一系列约束条件下,关联t时刻和t-1时刻图像帧中每个目标的成本。关联成本的最小化规划为一个优化组合问题。可以用最优分配方法求解,如匈牙利算法,贪婪搜索算法。(2)统计性方法在目标状态估计中考虑了观测噪声和模型不确定性,用状态空间方法建模速度、位置、加速度等目标属性。对于单个目标的情况,状态可简单估计得到;对于多目标的情况,则需要将观测域相应目标对应起来。

对于单目标状态估计:如果状态转移矩阵和观测矩阵都是线性的,状态和噪声是qsdmt分布的,则最优的状态估计方法是卡尔曼滤波。本博客最后的结果也是使用的卡尔曼滤波实现的,结果显示,对于但目标的追踪上,准确率还可以,多各目标时效果并不是太好。

对于 多目标状态估计:广泛采用的两种方法是Joint Probability Data Association Filtering (JPDAF)和Multiple Hypothesis Tracking (MHT)

核跟踪:

核函数可以是关联与一个直方图的矩形或椭圆模板,通过在连续帧中计算核的运动来跟踪。运动可以是参数形式的平移、旋转或仿射等。核跟踪的目标表达通常用原始的目标区域来表达,跟踪由计算目标运动来实现的。目标运动以参数形式的运动(如平移、仿射等)或计算得到的连续帧的密度流区域描述。这些算法在外观表达的运动、跟踪的目标数目、运动估计使用的方法等方面有所差异。核跟踪算法可分为两类:分别是基于模板和概率密度的外观模型的跟踪,和基于多视角外观模型跟踪。

单目标跟踪这类算法中最常用的是模板匹配。在图像中搜索类似于预定义模板的区域,通过相似性度量(比如cross correlation)判断目标位置。主要问题在于计算量大。可以用邻域范围限定等方法来减少搜索半径。除了模板匹配外,还可以用颜色直方图、混合模型等来表达外观模型。

多目标跟踪:这类算法通常对整个图像进行建模,包括背景和每个目标。

用多视角外观模型跟踪:对多个视角的目标进行离线学习,使能够处理重大视角变化情况跟踪问题。Black and Jepson[1998]提出基于子空间的方法。先用PCA建立目标外观的子空间表达,然后将图像转化到特征子空间中。Avidan [2001]使用了SVM分类器对多视角进行分类,并跟踪。

轮廓跟踪:

基于轮廓的方法提供了较为准确的形状描述。这类方法的主要思想是用先前帧建立的目标模型找到当前帧的目标区域。其中目标模型可以是颜色直方图、目标边缘或者轮廓。基于轮廓的跟踪方法可以分为两类:形状匹配方法和轮廓跟踪方法。前者在当前帧中搜索目标性状,后者则通过状态空间模型或直接的能量最小化函数推演初始轮廓在当前帧中的新位置。

形状匹配方法:这种方法类似于基于模板的跟踪,在当前帧中搜索目标的轮廓和相关模型。  另一种匹配形状的方法是在连续两帧中寻找关联轮廓,建立轮廓关联,或称为轮廓匹配,是类似于点匹配的一种方法。这种方法使用了目标的外观特征。轮廓检测通常由背景减除实现。轮廓被提取后,匹配由计算目标模型和每个轮廓之间的距离。目标模型可以使密度函数(颜色或边缘直方图)、轮廓边界、目标边缘或这些信息的组合。

自己实现的单目标追踪实验结果,主要是用的opencv中的函数,qsdmt混合模型提取前景,经过简单的处理得到轮廓和质心,再加上卡尔曼函数实现的。网上代码一大堆,有需要的可以可以提供。

  算法的主要流程如下: 计算帧间的距离(Pythagorean distance)在计算出来的距离矩阵上应用qsdmt模糊使用一定的阈值进行过滤计算标准差标准差大于一定的阈值,认为检测到了运动,输出信息

本文将给出 Python 语言的实现。

运行环境


编程环境:Python 3.7.6, OpenCV 3.3.0,IDEA

Python 实现 import numpy as npimport cv2sdThresh = 10font = cv2.FONT_HERSHEY_SIMPLEXdef distMap(frame1, frame2): """outputs pythagorean distance between two frames""" frame1_32 = np.float32(frame1) frame2_32 = np.float32(frame2) diff32 = frame1_32 - frame2_32 norm32 = np.sqrt(diff32[:,:,0]**2 + diff32[:,:,1]**2 + \ diff32[:,:,2]**2)/np.sqrt(255**2 + 255**2 + 255**2) dist = np.uint8(norm32*255) return distcv2.namedWindow('frame')cv2.namedWindow('dist')#capture video stream from camera source. 0 refers to first camera, 1 referes to 2nd and so on.cap = cv2.VideoCapture(0)_, frame1 = cap.read()_, frame2 = cap.read()facecount = 0while(True): _, frame3 = cap.read() rows, cols, _ = np.shape(frame3) cv2.imshow('dist', frame3) dist = distMap(frame1, frame3) frame1 = frame2 frame2 = frame3 # apply Gaussian smoothing mod = cv2.GaussianBlur(dist, (9,9), 0) # apply thresholding _, thresh = cv2.threshold(mod, 100, 255, 0) # calculate st dev test _, stDev = cv2.meanStdDev(mod) cv2.imshow('dist', mod) cv2.putText(frame2, "Standard Deviation - {}".format(round(stDev[0][0],0)), \ (70, 70), font, 1, (255, 0, 255), 1, cv2.LINE_AA) if stDev > sdThresh: print("Motion detected.. Do something!!!"); cv2.imshow('frame', frame2) if cv2.waitKey(1) & 0xFF == 27: breakcap.release()cv2.destroyAllWindows()


文章分类
代码人生
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐