精华内容
下载资源
问答
  • 雷达原理动目标检测及测速技术

    千次阅读 2020-05-20 21:45:01
    雷达原理笔记之动目标检测及测速技术 ——南京理工大学许志勇老师的《雷达原理课程》浅析 文章目录雷达原理笔记之动目标检测及测速技术1.杂波对消处理1.1任务1.2一次杂波对消器:1.3二次杂波对消器2多普勒滤波器组...

    雷达原理笔记之动目标检测及测速技术

    ——南京理工大学许志勇老师的《雷达原理课程》浅析


    动目标检测技术主要包括MTI杂波对消处理以及MTD窄带多普勒滤波组滤波处理。本文主要介绍这两个方面的实现原理及过程。

    1.杂波对消处理

    雷达检测目标常常是在强杂波背景中进行,信杂比非常小。这对目标探测很不利。考虑到杂波频谱通常比较稳定,大多在零多普勒附近,由此引出消除固定、低速杂波的滤波器——杂波对消器。

    1.1任务

    • 抑制固定杂波以及低速杂波,进而提取运动目标信息。

    1.2一次杂波对消器:

    y[n]=x[n]αx[n1] y[n]=x[n]-\alpha x[n-1]

    滤波器频率特性:
    H(z)=1αz1 H(z)=1-\alpha z^{-1}
    其中α\alpha通常取接近1但小于1的常数。目的是保证尽可能多地滤除杂波的同时,处在零多普勒点的运动目标不被抑制完全。对比见下图:
    在这里插入图片描述

    1.3二次杂波对消器

    y[n]=x[n]αx[n1]+x[n2] y[n]=x[n]-\alpha x[n-1]+x[n-2]

    滤波器频率特性:
    H(z)=1αz1+z2 H(z)=1-\alpha z^{-1}+z^{-2}
    其中α\alpha通常取接近2但小于2的常数。目的同样是在保证尽可能多地滤除杂波的同时,处在零多普勒点的运动目标不被抑制完全。对比见下图:

    在这里插入图片描述

    二次杂波对消器是工程中应用最多的杂波处理滤波器。对于低速的杂波消除,频响特性可以向右平移一定的区间,平移的量是杂波运动速度对应的多普勒频移。因此对于低速运动杂波对消的滤波特性为:
    H(z)=1αejβz1+ej2βz2 H(z)=1-\alpha e^{j\beta}z^{-1}+e^{j2\beta}z^{-2}
    其中β\beta为杂波速度对应的多普勒频移

    在这里插入图片描述

    利用二次杂波对消器处理杂波时,选取相参积累脉冲个数为K=2N+2K=2^N+2

    2多普勒滤波器组处理

    一般,将MTI处理后输出的信号进行MTD处理,即窄带滤波处理,得到运动目标的速度信息。

    2.1窄带多普勒滤波器组实现

    利用有N个输出的横向滤波器,经过各脉冲的加权求和实现。

    在这里插入图片描述

    每根延时线延迟时间T=1/PRFT=1/PRF。每个窄带滤波器输出的频率响应为:
    Hk(f)=ej2πfti=1Nej2π(i1)[fTk/N] H_k(f)=e^{-j2\pi ft}\sum_{i=1}^{N}e^{-j2\pi (i-1)[fT-k/N]}
    频响幅度为:
    Hk(f)=sin[πN(fTk/N)]sin[π(fTk/N)] |H_k(f)|=\frac{sin[\pi N(fT-k/N)]}{sin[\pi (fT-k/N)]}
    在这里插入图片描述

    上图所示的多普勒滤波器组,对应的发射信号脉冲重复频率为10kHz。其覆盖整个多普勒频谱周期[5000Hz,5000Hz][-5000Hz,5000Hz]。这个周期称作是多普勒滤波器组的主周期。此滤波器组长度N=8。每个窄带滤波器中心频率满足:
    f=5000k/N(Hz)(N=8,k=4,3,4) f=5000k/N(Hz)\quad (N=8,k=-4,-3,…4)
    若某运动目标的频谱出现在其中一个滤波器中,则该滤波器的中心频率对应的频率即为运动目标fdf_d的估值。

    当然,N取值越大对应的滤波器组间隔越小,运动目标的fdf_d的估值越接近真实值。

    利用多普勒滤波器组实现相参积累,可以将白噪声背景中信号的信噪比提高N倍。

    3.附录

    3.1一次相消器图片matlab代码

    clc
    close all
    clearvars
    a=0.8;
    T=1e-4;%发射信号周期
    f=-1/T:10:1/T;%频率轴
    w=2*pi*f;%角频率
    z=exp(1j*w*T);%映射到z轴
    H=1-a*z.^(-1);%滤波器传输函数表达式(针对静止杂波)
    figure
    subplot(1,2,1)
    plot(f,(abs(H)),'r-','LineWidth',2);
    title('\alpha=0.8')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    subplot(1,2,2)
    a=1;
    H=1-a*z.^(-1);%滤波器传输函数表达式(针对运动杂波)
    plot(f,(abs(H)),'r-','LineWidth',2);
    title('\alpha=1')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    suptitle('一次相消器幅度-频率响应曲线')
    

    3.2二次相消器图片matlab代码

    clc
    close all
    clearvars
    a=1.8;
    T=1e-4;%发射信号周期
    f=-1/T:10:1/T;%频率轴
    w=2*pi*f;%角频率
    z=exp(1j*w*T);%映射到z轴
    H=1-a*z.^(-1)+z.^(-2);%滤波器传输函数表达式(针对静止杂波)
    figure
    subplot(1,2,1)
    plot(f,(abs(H)),'b-','LineWidth',2);
    title('\alpha=1.8')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    subplot(1,2,2)
    a=2;
    H=1-a*z.^(-1)+z.^(-2);%滤波器传输函数表达式(针对运动杂波)
    plot(f,(abs(H)),'b-','LineWidth',2);
    title('\alpha=2')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    suptitle('二次相消器幅度-频率响应曲线')
    

    3.3二次相消器图片(静止、运动杂波)matlab代码

    clc
    close all
    clearvars
    k=1.7;
    T=1e-4;%发射信号周期
    f=-1/T:10:1/T;%频率轴
    w=2*pi*f;%角频率
    z=exp(1j*w*T);%映射到z轴
    H=1-k*z.^(-1)+z.^(-2);%滤波器传输函数表达式(针对静止杂波)
    figure
    subplot(1,2,1)
    plot(f,(abs(H)),'c-','LineWidth',2);
    title('针对静止杂波')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    subplot(1,2,2)
    b=0.2*1/T;%平移量0.2倍的频谱周期
    z1=exp(-1j*b)*z;%加上平移
    H=1-k*z1.^(-1)+z1.^(-2);%滤波器传输函数表达式(针对运动杂波)
    plot(f,(abs(H)),'c-','LineWidth',2);
    title('针对运动杂波')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    suptitle('二次相消器幅度-频率响应曲线')
    

    3.4多普勒滤波器组频响matlab代码

    clc
    close all
    clearvars
    N=8;
    T=1e-4;%发射信号周期
    f=-0.5/T:10:0.5/T;%频率轴
    for k=0:N-1
    H=(sin(pi*N*(f*T-k/N)))./(sin(pi*(f*T-k/N)));%滤波器传输函数表达式(针对静止杂波)
    plot(f,abs(H),'g-','LineWidth',2);
    hold on
    end
    title('窄带多普勒滤波器组')
    xlabel('f/Hz')
    ylabel('|H(f)|')
    
    展开全文
  • 在常规FM-CW SAR成像过程中可忽略的RVP项,在杂波对消时会引起严重通道相位失配,导致动目标检测失败,因此,在分析FM-CW SAR动目标检测原理的同时,重点研究了RVP对动目标检测结果的影响并给出补偿方法。...
  • 基于线性调频(LFM)脉冲压缩雷达原理及雷达动目标显示(MTI)的数学模型,通过与传统二脉冲对消和三脉冲对消的方法相对比,采用四脉冲对消和参差脉冲重复频率处理盲速的方法进行动目标检测。仿真实验证明,在动目标...
  • 目标检测中的mAP案例4). 总结5). 代码实现   文中如有错误,或您有不同的看法,请评论中指出讨论,谢谢。 概念:   得到检测算法的预测结果后,需要对pred bbox与gt bbox一起评估检测算法的性能,涉及到的评估...


      文中如有错误,或您有不同的看法,请评论中指出讨论,谢谢。

    概念:

      得到检测算法的预测结果后,需要对pred bbox与gt bbox一起评估检测算法的性能,涉及到的评估指标为mAP,那么当一个pred bbox与gt bbox的重合度较高(如IoU score > 0.5),且分类结果也正确时,就可以认为是该pred bbox预测正确,这里也同样涉及到IoU的概念;

    1). mAP相关概念

    • mAP: mean Average Precision, 即各类别AP的平均值
    • AP: PR曲线下面积,后文会详细讲解
    • PR曲线: Precision-Recall曲线
    • Precision(查准率): TP / (TP + FP)
    • Recall(召回率): TP / (TP + FN)
    • TP: IoU>0.5的检测框数量(同一Ground Truth只计算一次)
    • FP: IoU<=0.5的检测框,或者是检测到同一个GT的多余检测框的数量
    • FN: 没有检测到的GT的数量

      不管是Pascal VOC,还是COCO,甚至是人脸检测的wider face数据集,都使用到了AP、mAP的评估方式,那么AP、mAP到底是什么?如何计算的?

    2). 以图像检索mAP为例

    图像检索的案例取自:https://zhuanlan.zhihu.com/p/48992451

      那么mAP到底是什么东西,如何计算?我们先以图像检索中的mAP为例说明,其实目标检测中mAP与之几乎一样:

    在这里插入图片描述

      案例背景:目的是为了检验图片检索的算法。

      假设我们要从图库里查找和查询图片1类似的图片,而图库里实际存在图片1图片5五张图片是真正与查询图片1相似的。然后调用图片检索算法,设置算法找出的相似度排名前10的图片为最终结果,且计算出的相似度按顺序从大到小依次为返回图片1返回图片10。然后按图中顺序,每当召回率变化的时候计算一次recall和precision。最后把precision进行平均,即可得到检索算法对于查询图片1的AP1AP_1

      换一张查询图片2,重复上述过程,可以计算得到查询图片2的AP2AP_2

      那么此时图片检索算法的mAP=(AP1+AP2)/2mAP=(AP_1+AP_2)/2

    3). 目标检测中的mAP案例

      举例到此为止,那么mAP在目标检测中又是什么情况呢?其实和上述过程类似,上述过程的目的改成“为了检验目标检测算法”,而每次的查询图片1和2就相当于目标检测中的多个类别。图库中已知和查询图片相似的图片其实就是目标检测样本的ground truth。图片检索算法得到的10个检索结果就相当于目标检测中某个类别筛选出的bbox,相似度就相当于置信度(score)。既然对mAP在目标检测中的应用有了大致的概念,接下来直接举个例子加深印象。

    在这里插入图片描述

      假设上图最左边是我们目标检测算法(通常是NMS之后)得到的20个bbox的最原始数据,每个bbox的置信度为score,对应IoU最大的ground truth bbox是gt_label,而预测的类别是pred。

      然后我们按pred预测的类别进行分组,并在每个组内按置信度score进行排序。从而得到上图最右侧的数据表。

      然后根据分组,对每个类别的组,按score从大到小的顺序依次对比gt_label和pred,从而得到TP(真阳)、FP(假阳)和FN(假阴)样本的数量,并依次计算一一对应的precision和recall数组。具体过程见下面三个表格:

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

      理论上,根据precision及其对应的recall数组,可以绘制出Precision-Recall曲线图(如下三个曲线图),然后根据曲线图计算每个类别的AP(即图中红虚线围成的面积,这个是VOC2010版本的计算方法)。注意,在recall=x时,precision的数值是recall[x,1]recall \in [x, 1]范围内的最大precision。

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

      由此,可以计算出AP0=0.32,AP1=0.38,AP2=0.52AP_0=0.32,AP_1=0.38,AP_2=0.52。所以有:
    mAP=1Ci=0CAPi=0.4067 mAP=\frac{1}{C}\sum_{i=0}^CAP_i=0.4067

    4). 总结

      所以,目标检测中计算mAP的步骤总结如下,适用于VOC2010版本,当然,VOC2007版本也差不多,就是计算AP的方法略有不同而已。

    • 将目标检测算法预测出的每张图片的所有bbox数据经过NMS过滤后,整理成一个上图中最左侧的原始数据表;
    • 将所有bbox根据置信度score进行降序排序,并按算法预测的类别pred将所有bbox进行分组,注意,每组内也是按score降序排序;
    • 在每个分组内,分别计算precision和recall的数组,理论上可以得到PR曲线,但实际算法实现的时候并不需要。根据precision和recall数组计算每个类别的APiAP_i
    • 最后根据公式计算所有类别的mAP:

    mAP=1Ci=0CAPi=0.4067 mAP=\frac{1}{C}\sum_{i=0}^CAP_i=0.4067

      理论步骤是上面那样,实际代码实现也差不多,但是有些步骤代码实现的很简洁,可以学习一下。

    5). 代码实现

    import numpy as np
    
    def ap_per_class(tp, conf, pred_cls, target_cls):
        """
        计算所有类别的ap,precision,recall和f1指标。如果需要计算mAP,可以直接对ap取均值。
        代码来源:https://github.com/rafaelpadilla/Object-Detection-Metrics.
        :param tp: ndarray(1D), 元素类型为bool或0/1, tp[i]=true表示第i个bbox是真阳,也就是预测类别和真实类别相同。
        :param conf: ndarray(1D), 元素类型是float,取值范围为(0,1), 每个bbox的置信度。
        :param pred_cls: ndarray(1D), 对应每个bbox预测类别的标号, 取值范围为0,1,2,...,C-1
        :param target_cls: ndarray(1D), 对应与每个bbox的IoU最大的gt_bbox代表的类别标号, 取值范围为0,1,2,...,C-1
        :return: precision: 每个类别的查准率,
        recall: 每个类别的召回率,
        AP: 每个类别的AP,
        F1: 每个类别的F1指标,
        unique_classes.astype('int32'): 所有计算出AP的类别
        """
        # Sort by objectness  将所有数据根据置信度进行排序
        i = np.argsort(-conf)  # 加负号是为了降序排列
        tp, conf, pred_cls = tp[i], conf[i], pred_cls[i]
    
        # Find unique classes  找出所有不重复的目标类别
        unique_classes = np.unique(target_cls)
    
        # Create Precision-Recall curve and compute AP for each class
        # 计算每个类别的Precision-Recall曲线的数据,并以此计算每个类别的AP
        AP, precision, recall = [], [], []
        for c in unique_classes:
            i = pred_cls == c  # 掩模,用来排除所有预测出来不是c类的bbox
            n_gt = (target_cls == c).sum()  # Number of ground truth objects  第c类真实标签的数量
            n_p = i.sum()  # Number of predicted objects  预测为c类的bbox数量
    
            if n_p == 0 and n_gt == 0:
                continue
            elif n_p == 0 or n_gt == 0:
                AP.append(0)
                recall.append(0)
                precision.append(0)
            else:
                # Accumulate FPs and TPs  计算TP和FP的累加数组,方便计算Precision-Recall曲线的数据
                FPc = (1 - tp[i]).cumsum()
                TPc = (tp[i]).cumsum()
    
                # Recall = TP/n_GT
                recall_curve = TPc / (n_gt + 1e-16)
                recall.append(recall_curve[-1])  # 将每个类别组的召回率保存起来
    
                # Precision = TP/(TP+FP)
                precision_curve = TPc / (TPc + FPc)
                precision.append(precision_curve[-1])  # 将每个类别组的查准率保存起来
    
                # AP from recall-precision curve  利用Precision-Recall曲线的数据计算该类的AP
                AP.append(compute_ap(recall_curve, precision_curve))
    
                # Plot  绘制PR曲线图(如有需要)
                # plt.plot(recall_curve, precision_curve)
    
        # Compute F1 score (harmonic mean of precision and recall)
        precision, recall, AP = np.array(precision), np.array(recall), np.array(AP)
        F1 = 2 * precision * recall / (precision + recall + 1e-16)
    
        return precision, recall, AP, F1, unique_classes.astype('int32')
    
    
    def compute_ap(recall, precision):
        """
        计算Precision-Recall曲线的AP,VOC2010版
        代码来源:https://github.com/rbgirshick/py-faster-rcnn.
        :param recall: ndarray(1D),Precision-Recall曲线的recall数据
        :param precision: ndarray(1D),Precision-Recall曲线的precision数据
        :return: ndarray(1D),Precision-Recall曲线的AP,VOC2010版
        """
        # correct AP calculation
        # first append sentinel values at the end  给Precision-Recall曲线添加头尾
        mrec = np.concatenate(([0.], recall, [1.]))
        mpre = np.concatenate(([0.], precision, [0.]))
    
        # compute the precision envelope  
        # 简单的应用了一下动态规划,实现在recall=x时,precision的数值是recall=[x, 1]范围内的最大precision
        for i in range(mpre.size - 1, 0, -1):
            mpre[i - 1] = np.maximum(mpre[i - 1], mpre[i])
    
        # to calculate area under PR curve, look for points where X axis (recall) changes value
        # 寻找recall[i]!=recall[i+1]的所有位置,即recall发生改变的位置,方便计算PR曲线下的面积,即AP
        i = np.where(mrec[1:] != mrec[:-1])[0]
    
        # and sum (\Delta recall) * prec
        # 用积分法求PR曲线下的面积,即AP
        ap = np.sum((mrec[i + 1] - mrec[i]) * mpre[i + 1])
        return ap
    
    if __name__ == '__main__':
        # 一下测试数据与上文举例中的数据相同,用来验证上文计算mAP的思想
        tp = np.array([True, True, False, True, False,
              True, True, True, False, True,
              False, False, False, True, True,
              False, False, False, True, True,])
        conf = np.array([0.3062, 0.3482, 0.3916, 0.3894, 0.1796,
                0.0007, 0.5094, 0.1176, 0.7718, 0.9761,
                0.1734, 0.3216, 0.5173, 0.5339, 0.6169,
                0.2016, 0.2489, 0.5887, 0.8256, 0.9008])
        pred_cls = np.array([1, 1, 0, 0, 2, 2, 2, 0, 1, 0,
                    0, 2, 0, 1, 1, 1, 0, 1, 2, 2])
        gt_cls = np.array([1, 1, 1, 0, 0, 2, 2, 0, 0, 0,
                  2, 1, 1, 1, 1, 0, 2, 2, 2, 2,])
        ap_per_class(tp, conf, pred_cls, gt_cls)
    
          0, 2, 0, 1, 1, 1, 0, 1, 2, 2])
        gt_cls = np.array([1, 1, 1, 0, 0, 2, 2, 0, 0, 0,
                  2, 1, 1, 1, 1, 0, 2, 2, 2, 2,])
        ap_per_class(tp, conf, pred_cls, gt_cls)
    
    展开全文
  • 雷达原理-运动目标检测与测速

    千次阅读 多人点赞 2020-07-10 18:12:24
    文章目录多普勒效应及其应用动目标显示雷达盲速、盲相的影响及其解决途径回波和杂波的频谱及动目标显示滤波器动目标检测(MTD) 多普勒效应及其应用 多普勒效应 连续波雷达 连续波雷达收发天线不共用 脉冲雷达...

    本篇博文是看完西安电子科技大学的魏青老师的课程所做的学习笔记,特此记录。

    多普勒效应及其应用

    1. 多普勒效应
      1. 连续波雷达
        在这里插入图片描述
        连续波雷达收发天线不共用
      2. 脉冲雷达(脉冲多普勒雷达)
        在这里插入图片描述
    2. 多普勒信息的提取
      1. 连续波雷达
        相位检波器:将发射的信号与接收到的信号进行混频,取低通。
        连续波多普勒雷达的组成方框图
        在这里插入图片描述
        通过相位检波器得到的多普勒频率信号为:
        在这里插入图片描述
      2. 脉冲雷达
        多普勒效应的脉冲雷达的原理方块图和主要波形
        在这里插入图片描述
    3. 盲速和频闪
      1. 盲速
        盲速是指当目标虽然有一定的径向速度vr,但若其回波信号经过相位检波器后,输出为一串等幅脉冲,与固定目标的回波相同,此时的目标速度为盲速
        盲速产生的原因:当fd=nfr时,运动目标回波的谱线由nfr组成,频谱结构与固定目标回波的相同,这是无法区分运动目标与固定目标
        盲速说明:
        在这里插入图片描述
      2. 频闪
        频闪说明:
        在这里插入图片描述
        频闪是指当脉冲工作状态时,相位检波器输出端回波脉冲串的包络调制频率Fd与目标运动的径向速度vr不再保持正比例关系,此时如用包络调制频率测速时将产生测速模糊。
        频闪产生的原因:当多普勒频率fd超过重复频率fr一半时,频率nfr的上边频分量nfr+fd与频率(n+1)fr-fd在谱线排列的前后位置上交叉。两个不同的多普勒频率fd1和fd2,只要满足fd1=nfr-fd2,则二者的谱线位置相同而无法区分。
        避免频闪:|fd|<=fr/2

    动目标显示雷达

    1. 基本工作原理
      经过相捡后,去除固定目标回波
    2. 中频部分进行相检原理
      在这里插入图片描述
    3. 消除固定目标回波
      一次相消器
      在这里插入图片描述
      当wdTr/2=nπ(n=1,2,3,……)时,输出振幅为零。这时的目标速度相当于盲速。此时,运动目标回波在相位检波器的输出端与固定目标的回波相同,因此经过相消设备后输出为零。
      求解相消设备的频率相应特性:
      在这里插入图片描述

    盲速、盲相的影响及其解决途径

    1. 盲速
      1. 盲速出现的条件
        在这里插入图片描述
        最大不模糊距离R0max和第一盲速vr0’的关系:
        在这里插入图片描述
      2. 重频参差
        fd=n*(fr1与fr2的最小公倍数)
    2. 盲相
      1. 分类
        盲相问题是由检波器特性所引起的
        相位检波器输出经一次相消器后,运动目标回波为:
        在这里插入图片描述
        在某些点上,输出幅度为零,这些点称为盲相,它由相位检波器的特性决定。从相检特性上看,如果相邻两个回波的脉冲的相位相当于相检特性的a、c两点,其相位差虽不同,但却是一对相检器输出相等的工作点,因此,经过相消器后,其输出为零而出现盲相
        相检特性和相消器输出脉冲波形
        在这里插入图片描述
        用矢量图来说明相消器的输出。匀速运动目标的回波信号用围绕基准电压均匀旋转的一个矢量来表示,旋转的速度等于其多普勒频率。相检器的输出为该矢量沿基准电压方向的投影,如下图所示,
        在这里插入图片描述
        当差矢量垂直于该轴时,投影长度为零而出现点盲相
        下图表示动目标与固定目标叠加:
        在这里插入图片描述
        如果运动目标回波叠加在固定杂波上,则在一般情况下也将产生点盲相。
        如果回波叠加在很强的杂波上,可能产生连续盲相:接收机的限幅作用使动目标和固定杂波的合成矢量变成端点在限幅电平的一小段圆弧上来回摆动的矢量
        在这里插入图片描述
      2. 解决办法
        1. 中频对消
          在这里插入图片描述
        2. 零中频(I、Q双通道处理)
          原理框图:
          在这里插入图片描述
          用正交双通道,则二路可以同时得到两个投影I和Q,它们互相正交,当一个为零时,另一个值最大。

    回波和杂波的频谱及动目标显示滤波器

    1. 回波信号和杂波的频谱
      1. 雷达回波信号的频谱
        在这里插入图片描述
        天线扫描条件下的回波信号谱
        在这里插入图片描述
      2. 杂波频谱
        在这里插入图片描述
    2. 动目标显示滤波器
      在这里插入图片描述

    动目标检测(MTD)

    1. 动目标检测的特点
      1. 动态范围更大
      2. 改善因子提高
        在这里插入图片描述
      3. 增加滤波器组
      4. 抑制杂波
      5. 增加杂波图
    2. 多普勒滤波器组
      具有N个输出的横向滤波器(N个脉冲和N-1根延迟线)经过各脉冲不同的加权并求和后,可以做成N个相邻的窄带滤波器组。该滤波器组的频率覆盖范围为0~fr,fr为雷达工作重复频率
      如下图所示(横向滤波器):
      在这里插入图片描述
      横向滤波器有N-1根延迟线,每根延迟线的延迟时间为Tr=1/fr。
      在这里插入图片描述
      上图b表示的是N=8时滤波器所得各标记k的滤波器频率响应
      在这里插入图片描述

    当幸福来敲门


    下面的是笔者的微信公众号,欢迎关注,会持续更新c++、python、tensorflow、机器学习、深度学习、计算机视觉、雷达原理等系列文章。
    在这里插入图片描述

    展开全文
  • 为了对视频序列中的运动目标进行快速、准确地提取,提出了一种自适应背景模型估计方法。利用背景与前景图像在时域中不同的变化特性,构造图像的稳定矩阵函数,通过稳定矩阵元素的变化自动区分背景点和前景点,并对稳定...
  • 主要介绍当前主要目标运动检测方法的原理和利用,对这些算法有一个初步了解,文章中设计借鉴其他文章,在这里一一感谢。

    一、光流法

      1.1光流法原理 

       光流的概念是Gibson1950年首先提出来的。它是空间运动物体在观察成像平面上的像素运动的瞬时速度,是利用图像序列中像素在时间域上的变化以及相邻帧之间的相关性来找到上一帧跟当前帧之间存在的对应关系,从而计算出相邻帧之间物体的运动信息的一种方法。一般而言,光流是由于场景中前景目标本身的移动、相机的运动,或者两者的共同运动所产生的。其计算方法可以分为三类:

           (1)基于区域或者基于特征的匹配方法;

           (2)基于频域的方法;

           (3)基于梯度的方法;

        简单来说,光流是空间运动物体在观测成像平面上的像素运动的“瞬时速度”。光流的研究是利用图像序列中的像素强度数据的时域变化和相关性来确定各自像素位置的“运动”。研究光流场的目的就是为了从图片序列中近似得到不能直接得到的运动场。

    光流法的前提假设:

          (1)相邻帧之间的亮度恒定;

          (2)相邻视频帧的取帧时间连续,或者,相邻帧之间物体的运动比较“微小”;

          (3)保持空间一致性;即,同一子图像的像素点具有相同的运动

    这里有两个概念需要解释:

    运动场,其实就是物体在三维真实世界中的运动;

    光流场,是运动场在二维图像平面上的投影。




    如上图所示,H中的像素点(x,y)I中的移动到了(x+u,y+v)的位置,偏移量为(u,v)

    光流法用于目标检测的原理:给图像中的每个像素点赋予一个速度矢量,这样就形成了一个运动矢量场。在某一特定时刻,图像上的点与三维物体上的点一一对应,这种对应关系可以通过投影来计算得到。根据各个像素点的速度矢量特征,可以对图像进行动态分析。如果图像中没有运动目标,则光流矢量在整个图像区域是连续变化的。当图像中有运动物体时,目标和背景存在着相对运动。运动物体所形成的速度矢量必然和背景的速度矢量有所不同,如此便可以计算出运动物体的位置。需要提醒的是,利用光流法进行运动物体检测时,计算量较大,无法保证实时性和实用性。

    光流法用于目标跟踪的原理:

    (1)对一个连续的视频帧序列进行处理;

    (2)针对每一个视频序列,利用一定的目标检测方法,检测可能出现的前景目标;

    (3)如果某一帧出现了前景目标,找到其具有代表性的关键特征点(可以随机产生,也可以利用角点来做特征点);

    (4)对之后的任意两个相邻视频帧而言,寻找上一帧中出现的关键特征点在当前帧中的最佳位置,从而得到前景目标在当前帧中的位置坐标;

    (5)如此迭代进行,便可实现目标的跟踪;


    1.2 光流法实现

     1.2.1、opencv下的光流L-K算法

    opencv的光流实现由好几个方法可以(也就是说有好几个函数可以用),每个函数当然也对应着不同的原理,那么它的效果以及算法的速度等等就会有一些差别。主要包括以下几种: 
    calcOpticalFlowPyrLK 
    calcOpticalFlowFarneback 
    calcOpticalFlowBM 
    calcOpticalFlowHS 
    calcOpticalFlowSF

    参见opencv文档介绍

    这里先简单介绍下calcOpticalFlowPyrLK函数 
    calcOpticalFlowPyrLK函数使用形式: 
    calcOpticalFlowPyrLK(prevImg,nextImg,prevPts,nextPts,status,err) 
    这个函数还有一些可选参数,一大堆,详细的说明可以看opencv介绍

    这里只是贴出了主要的几个输入输出: 
    prevImg:就是你需要输入计算光流的前一帧图像

    nextImg就是下一帧图像(可以看到一次光流就是在两针图像之间找不同)。

    prevPts是前一帧图像中的特征点,这个特征点必须自己去找,所以在使用calcOpticalFlowPyrLK函数的时候,前面需要有一个找特征点的操作,那么一般就是找图像的角点,就是一个像素点与周围像素点都不同的那个点,这个角点特征点的寻找,opencv也提供夜歌函数:goodFeatureToTrack()(后面再介绍这个函数)。那么关于特征点有没有其他的方式呢?肯定是有的而且还很多吧。

    nextPts参数就是计算特征点在第二幅图像中的新的位置,然后输出。特征点的新位置可能变化了,也可能没有变化,那么这种状态就存放在后一个参数status中。err就是新旧两个特征点位置的误差了,也是一个输出矩阵。 
    其他参数默认吧。

    关于特征角点检测函数goodFeatureToTrack() 
    goodFeaturesToTrack(image,corners,maxCorners,qualityLevel,minDistance) 
    函数的参数: 
    image输入图像; 
    corners输出的特征点系列,每一个元素就是一个特征点的位置。 
    maxCorners规定的特征点最大数目,比如一副图像你可以找到很多特征点,但是只是取前maxCorners个具有最大特征的那些点作为最后的特征点,至于怎么判断哪些点的特征更好了,opencv自有一个机制,随便一个方法,比如计算一下这个点与周围一定领域的点的灰度相差求和,认为这个和越大的那些点是不是越属于特征点。 
    qualityLevel是一个特征点的取到水平,其实也是控制特征点的选取的,看结果适当选取吧。 
    minDistance是特征点与点之间的最小距离,一般我们如果想特征点尽量分散一些,太密集了肯定不好,那么我们可以通过这个参数。

    比如说一个例子如下:

    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <iostream>
    
    using namespace std;
    using namespace cv;
    int main()
    {
        Mat I1;
        Mat I2;
        vector<Point2f> features;
        int maxCout = 50;//定义最大个数
        double minDis = 20;//定义最小距离
        double qLevel = 0.01;//定义质量水平
    
        I1 = imread("I1.jpg",0);//读取为灰度图像
        goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis);
        for(int i=0;i<features.size();i++)
        {
            //将特征点画一个小圆出来--粗细为2
            circle(I1,features[i],3,Scalar(255),2);
        }
        imshow("features",I1);
        waitKey(0);
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    这里写图片描述

    修改下 int maxCout = 100;//定义最大个数 
    double minDis = 10;//定义最小距离

    这里写图片描述

    下面通过这种特征点来以及L-K光流法来检测两幅相邻帧图像之间的移动点。首先自己准备两幅图吧,图中要有运动的目标才好,然后我们就这两幅图简单的看下里面的运动目标的特征点的运动吧,一个简单程序如下:

    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/video/video.hpp>
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/types_c.h>
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    using namespace cv;
    int main()
    {
        Mat I1;
        Mat I2;
        vector<Point2f> features;
        vector<Point2f> features_after;
        vector<uchar> status;
        vector<float> err;
        int maxCout = 300;//定义最大个数
        double minDis = 10;//定义最小距离
        double qLevel = 0.01;//定义质量水平
        //读取两个图像---相邻帧
        I1 = imread("I1.jpg",0);//读取为灰度图像
        I2 = imread("I2.jpg",0);
        //检测第一帧的特征点
        goodFeaturesToTrack(I1,features,maxCout,qLevel,minDis);
        //计算出第二帧的特征点
        calcOpticalFlowPyrLK(I1,I2,features,features_after,status,err);
        //判别哪些属于运动的特征点
        int k = 0;
        for(int i=0;i<features_after.size();i++)
        {
            //状态要是1,并且坐标要移动下的那些点
            if(status[i]&&((abs(features[i].x-features_after[i].x)+
                abs(features[i].y-features_after[i].y))>4))
            {
                features_after[k++] = features_after[i];
            }
        }
        features_after.resize(k);//截取
        cout<<k<<endl;
        for(int i=0;i<features_after.size();i++)
        {
            //将特征点画一个小圆出来--粗细为2
            circle(I1,features_after[i],3,Scalar(255),2);
        }
        imshow("features",I1);
        waitKey(0);
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50

    这里写图片描述

    我的这两幅树叶图是存在这一些变化的,尤其树存在的地方,由于需要动态的来回切换着看才能看出变化,所以这里不太好显示这两幅图的变化,这里吧他们相差的图做出来如下: 
    这里写图片描述

    可以看到的是越白的地方就是存在着不一致,也就是存在着明显运动的地方。和上面角点检测的还是有点符合的。 
    当然,我这可能只是连续两帧运动情况下的跟踪的特征点,如果是一个视频(连续的很多帧),那么把每两帧之间的运动点连接起来,就可以发现运动的物体的整个轨迹了。像网上博客有人做过的贴几个: Opencv学习笔记(九)光流法

    1.2.2、opencv下光流Farneback法

    上节说到过的calcOpticalFlowPyrLK光流算法,可以看到它实际上是一种稀疏特征点的光流算法,也就是说我们先找到那些(特征)点需要进行处理,然后再处理,该节介绍下一个全局性的密集光流算法,也就是对每一个点都进行光流计算,函数为calcOpticalFlowFarneback。

    首先介绍参数,详细的介绍 参见OpenCV手册

    参数一大推,得看一会。有些参数可能带来的影响不是很大,那么使用它推荐的参数即可。完整的参数达10个。按顺序:

    prevImg:输入第一个图 
    nextImg:输入第二个图 
    Flow:输出的光流矩阵。矩阵大小同输入的图像一样大,但是矩阵中的每一个元素可不是一个值,而是两个值,分别表示这个点在x方向与y方向的运动量(偏移量)。所以要把这个光流场矩阵显示出来还真的需要费点力。那么上面说的两幅图像与这个光流场是什么关系呢?如下:
    这里写图片描述 
    pyrScale:一个构造图像金字塔的参数,一般就认为是0.5最好了,也就是将图像缩小一半。那么为什么要构造金字塔呢?这应该是与算法本身的设计有关,其实很多地方在检测特征的时候都会涉及到图像的金字塔,设想下如果有个特征点在原始尺寸与其缩小的尺寸下都是特征点的话,那么这个特征点就很有效了吧。
    Levels:依然是与金字塔有关参数,常设值1. 
    Winsize:相当于一个均值滤波的作用,窗口大小决定了其噪声的抑制能力什么的。 
    Iterations:在每层金字塔上的迭代次数。 
    polyN:点与附近领域点之间的联系作用,一般为5,7等等即可。 
    polySigma :像素点的一个平滑水平,一般1-1.5即可。 
    Flags:一个标记,决定计算方法。

    具体怎么影响结果的,可以自己去尝试。 
    下面对上节使用到的两幅图,通过这个方法来计算这两帧图像中存在的光流场,也就是把上述的Flow找出来,那些参数也决定了Flow找出来的不一样。简单的程序如下:

    #include <opencv2/highgui/highgui.hpp>
    #include <opencv2/imgproc/imgproc.hpp>
    #include <opencv2/video/video.hpp>
    #include <opencv2/core/core.hpp>
    #include <opencv2/imgproc/types_c.h>
    #include <iostream>
    #include <cstdio>
    
    using namespace std;
    using namespace cv;
    #define UNKNOWN_FLOW_THRESH 1e9  
    
    void makecolorwheel(vector<Scalar> &colorwheel)  
    {  
        int RY = 15;  
        int YG = 6;  
        int GC = 4;  
        int CB = 11;  
        int BM = 13;  
        int MR = 6;  
    
        int i;  
    
        for (i = 0; i < RY; i++) colorwheel.push_back(Scalar(255,       255*i/RY,     0));  
        for (i = 0; i < YG; i++) colorwheel.push_back(Scalar(255-255*i/YG, 255,       0));  
        for (i = 0; i < GC; i++) colorwheel.push_back(Scalar(0,         255,      255*i/GC));  
        for (i = 0; i < CB; i++) colorwheel.push_back(Scalar(0,         255-255*i/CB, 255));  
        for (i = 0; i < BM; i++) colorwheel.push_back(Scalar(255*i/BM,      0,        255));  
        for (i = 0; i < MR; i++) colorwheel.push_back(Scalar(255,       0,        255-255*i/MR));  
    }  
    
    void motionToColor(Mat flow, Mat &color)  
    {  
        if (color.empty())  
            color.create(flow.rows, flow.cols, CV_8UC3);  
    
        static vector<Scalar> colorwheel; //Scalar r,g,b  
        if (colorwheel.empty())  
            makecolorwheel(colorwheel);  
    
        // determine motion range:  
        float maxrad = -1;  
    
        // Find max flow to normalize fx and fy  
        for (int i= 0; i < flow.rows; ++i)   
        {  
            for (int j = 0; j < flow.cols; ++j)   
            {  
                Vec2f flow_at_point = flow.at<Vec2f>(i, j);  
                float fx = flow_at_point[0];  
                float fy = flow_at_point[1];  
                if ((fabs(fx) >  UNKNOWN_FLOW_THRESH) || (fabs(fy) >  UNKNOWN_FLOW_THRESH))  
                    continue;  
                float rad = sqrt(fx * fx + fy * fy);  
                maxrad = maxrad > rad ? maxrad : rad;  
            }  
        }  
    
        for (int i= 0; i < flow.rows; ++i)   
        {  
            for (int j = 0; j < flow.cols; ++j)   
            {  
                uchar *data = color.data + color.step[0] * i + color.step[1] * j;  
                Vec2f flow_at_point = flow.at<Vec2f>(i, j);  
    
                float fx = flow_at_point[0] / maxrad;  
                float fy = flow_at_point[1] / maxrad;  
                if ((fabs(fx) >  UNKNOWN_FLOW_THRESH) || (fabs(fy) >  UNKNOWN_FLOW_THRESH))  
                {  
                    data[0] = data[1] = data[2] = 0;  
                    continue;  
                }  
                float rad = sqrt(fx * fx + fy * fy);  
    
                float angle = atan2(-fy, -fx) / CV_PI;  
                float fk = (angle + 1.0) / 2.0 * (colorwheel.size()-1);  
                int k0 = (int)fk;  
                int k1 = (k0 + 1) % colorwheel.size();  
                float f = fk - k0;  
                //f = 0; // uncomment to see original color wheel  
    
                for (int b = 0; b < 3; b++)   
                {  
                    float col0 = colorwheel[k0][b] / 255.0;  
                    float col1 = colorwheel[k1][b] / 255.0;  
                    float col = (1 - f) * col0 + f * col1;  
                    if (rad <= 1)  
                        col = 1 - rad * (1 - col); // increase saturation with radius  
                    else  
                        col *= .75; // out of range  
                    data[2 - b] = (int)(255.0 * col);  
                }  
            }  
        }  
    }  
    
    
    int main()
    {
        Mat I1;
        Mat I2;
        Mat flow;
        //读取两个图像---相邻帧
        I1 = imread("I1.jpg",0);//读取为灰度图像
        I2 = imread("I2.jpg",0);
        calcOpticalFlowFarneback(I1,I2,flow,0.5,3,20,3,5,1.2,0);
        //cout<<I1.size()<<flow.size()<<flow.at<Vec2f>(10,10)<<endl;
        //flow = abs(flow);
        Mat motion2color;  
        motionToColor(flow, motion2color);  
        imshow("flow",motion2color);
        waitKey(0);
        return 0;
    }
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114

    可以看到程序的大部分是在如何把计算的光流flow可视化出来,虽然我们已经知道它是一个矩阵,而且矩阵中每个元素都包括2个值。但是显示出来也比较费劲,显示的函数是参考博客:

    光流Optical Flow介绍与OpenCV实现

    该博客里面的内容也是值得一看的。 
    那么我们这里的一个结果如下(原始图见上篇): 
    这里写图片描述

    颜色越深表示该部分存在的运动变化越大。

    早点版本(3.0之前)的OpenCV中还有好几个光流计算函数,什么块匹配BM法,HS法,LK法等等,每一种方法几乎都对应一篇相关文章而来。后几种方法的结果无非也都是计算出光流场(在x方向的光流与在y方向的光流)。3.0的opencv似乎把块匹配、HS等方法舍弃了?没有找到,想使用那些方法的恐怕还要使用以前的opencv版本才行

    二、背景减法

    1、原理

           对于一个稳定的监控场景而言,在没有运动目标,光照没有变化的情况下,视频图像中各个像素点的灰度值是符合随机概率分布的。由于摄像机在采集图像的过程中,会不可避免地引入噪声,这些灰度值以某一个均值为基准线,在附近做一定范围内的随机振荡,这种场景就是所谓的“背景”。

            背景减法(Background subtraction)是当前运动目标检测技术中应用较为广泛的一类方法,它的基本思想和帧间差分法相类似,都是利用不同图像的差分运算提取目标区域。不过与帧间差分法不同的是,背景减法不是将当前帧图像与相邻帧图像相减,而是将当前帧图像与一个不断更新的背景模型相减,在差分图像中提取运动目标。

                                    

        背景减法的运算过程如图2-6所示。首先利用数学建模的方法建立一幅背景图像帧B,记当前图像帧为fn,背景帧和当前帧对应像素点的灰度值分别记为B(x,)fn(x , ,按照式2.17将两帧图像对应像素点的灰度值进行相减,并取其绝对值,得到差分图像D n

                                          

        设定阈值 ,按照式2.18逐个对像素点进行二值化处理,得到二值化图像 Rn' 。其中,灰度值为255的点即为前景(运动目标)点,灰度值为0的点即为背景点;对图像 Rn'进行连通性分析,最终可得到含有完整运动目标的图像Rn 

                                         

        背景减法计算较为简单,由于背景图像中没有运动目标,当前图像中有运动目标,将两幅图像相减,显然可以提取出完整的运动目标,解决了帧间差分法提取的目标内部含有“空洞”的问题。

        利用背景减法实现目标检测主要包括四个环节:背景建模,背景更新,目标检测,后期处理。其中,背景建模和背景更新是背景减法中的核心问题。背景模型建立的好坏直接影响到目标检测的效果。所谓背景建模,就是通过数学方法,构建出一种可以表征“背景”的模型。获取背景的最理想方法是在没有运动目标的情况下获取一帧“纯净”的图像作为背景,但是,在实际情况中,由于光照变化、雨雪天气、目标运动等诸多因素的影响,这种情况是很难实现。

    2、背景建模

     2.1  多阵平均法

         

    当实际的监控场景不是太复杂时,可以采用多帧平均法建立背景模型。多帧平均法实质上是一种统计滤波的思想。在一段时间内,将采集到的多帧图像相加,求其平均值,这个平均值就作为参考的背景模型。具体计算式如下:

                                               

           上式中,Bn为采集到第n帧图像时系统建立的背景模型,N为进行平均的帧数,(fn,fn− 1 ...fn N +1 为包含当前帧在内的系统所保存的连续N帧图像。由于受到场景中光照变化等因素的影响,得到的背景模型Bn 每隔一段时间需要更新一次,更新计算式为:                                                                       

                                         

    2.20说明新的一帧背景模型可以由上一次计算得到的背景模型Bn1、当前帧fn以及fn -N帧递推得到,这样就实现了背景模型的更新。显然,N值越大,得到的背景模型Bn就越接近于真实背景。


                                                 


        图 2-7 是采用多帧平均法对标准序列 hall 序列进行目标检测的实验结果。观察图(b)可以发现,使用多帧平均法提取背景图像,当场景中存在运动目标时,提取的背景中会存在“鬼影”(ghosts),这是由目标在连续多帧图像中的运动造成的。当N值增大时,“鬼影”效应会有所减弱,但是很难消除。
        多帧平均法计算方法简单,对场景中背景变化的适应性较好,但是该方法需要保存前N帧图像信息,增加了系统的开销,特别是在实时监控系统中,这样大的内存开销是很浪费的。因此,多帧平均法在实际的监控系统中应用较少。

      2.2.2 高斯混合模型  

        使用统计的方法实现背景建模及运动目标检测是当前目标检测方法中效果较好的一类方法。该类方法利用统计值表征背景,建立背景模型。

        不同的监控场景有着不同的特性,背景模型因此分为单模态和多模态两种。单模态的场景中,每个背景像素点的颜色值分布比较集中,可以用单一分布的概率模型来描述背景;而在多模态的场景中,每个背景像素点的颜色值分布非常分散,需要用多个分布的概率模型相拟合描述背景。在实际的场景中,由于光照变化、背景中轻微扰动(如户外场景中树枝的轻微摇摆)等因素的影响,背景模型往往是多模态的。

        利用高斯混合模型实现背景建模就是用来描述多模态场景的一种方法。该方法能在不断更新背景模型的同时,在新一帧图像中直接检测出属于目标的像素点,减少了计算差分图像和二值化图像等环节,有效地提高了检测速度。算法的基本思想是:对图像中每一个像素点的颜色值建立混合高斯模型,通过一段时间的采样观测,根据各个高斯分布的持续性和变动性的差异,判断哪一个分布更加接近于真实背景,该高斯分布就作为背景模型。如果图像中像素点的颜色值不符合该高斯分布,则被认为是目标点。具体计算方法如下。
        设图像中位置为(x0, y0)的像素点在一段时间内的观测值为:

                                     
        利用多个高斯分布对式2.21中的观测值进行建模,可以得到当前像素点的颜色值概率为:

                                     
        其中,K为高斯分布的个数(通常取3-5);ωi,t,为权重的估计值,即t时刻该像素点属于第i个高斯分布的可能性的大小;μi,t,t时刻第i个高斯分布的均值;Σi,t为第i个高斯分布的协方差矩阵;η为高斯分布概率密度函数:

                                    
        为了计算简便,假定像素点颜色值的三个分量(R,G,B)相互独立,并且具有相同的方差,则式2.23中的协方差矩阵可以写为:
                                             

        这样,就建立起了被观察像素点(x0,y0)颜色值的高斯混合模型。对于输入图像中的像素点(x0,y0,t),将它的颜色值与已存在的个高斯分布相比较,判断其是否和已经存在的高斯分布相匹配,如果匹配,则该像素点为背景点。所谓“匹配”,即满足式2.25
                                         
        其中,μi,t-1 ,为第i个高斯分布在t1时刻的均值,TH通常取2.5σi t-1 ,为第i个高斯分布在t1时刻的标准偏差。
        如果没有找到匹配的高斯分布,则将输入像素的颜色值作为均值,建立一个新的高斯分布,代替之前K个高斯分布中概率最小、权重最低的分布,该分布具有较大的方差和较低的权重,从而重新建立背景模型。
        如果存在匹配的高斯分布,则背景模型中各个参数进行如下更新:

                                         
       其中,α是模型学习速率,1/α表征了模型参数变化的速率;对于匹配的高斯分布 Mk,t 1,其余不匹配的高斯分布,M k,t0;式2.27 和式 2.28 只针对于匹配的高斯分布,其余不匹配的高斯分布对应的参数保持不变;ρ为参数学习速率,定义为:

                                          
        这样,通过式 2.26--2.29,就实现了高斯混合模型的更新。高斯混合模型的方法,能够充分表征场景的多模态特性;可以很快适应背景的变化,即使是当场景中有光照变化、小幅度重复运动(如户外场景中树枝的轻微扰动)时,也能检测出运动目标;如果场景中有目标进入,长时间停留而成为背景,高斯混合模型方法同样可以及时地更新背景模型。
                        
        图2-8是采用高斯混合模型方法对自拍序列 lab 序列进行目标检测的实验结果。由图可以看出,该方法提取的背景较为“纯净”,最终可以获得完整的运动目标。但是该方法受光照变化的影响较大,提取的目标往往存在阴影;提取的前景(目标)图像中,含有较多的噪声,这都需要相应的后期处理操作。

    三、帧间差分法

    1、原理

        摄像机采集的视频序列具有连续性的特点。如果场景内没有运动目标,则连续帧的变化很微弱,如果存在运动目标,则连续的帧和帧之间会有明显地变化。

        帧间差分法(Temporal Difference)就是借鉴了上述思想。由于场景中的目标在运动,目标的影像在不同图像帧中的位置不同。该类算法对时间上连续的两帧或三帧图像进行差分运算,不同帧对应的像素点相减,判断灰度差的绝对值,当绝对值超过一定阈值时,即可判断为运动目标,从而实现目标的检测功能。

                          

        两帧差分法的运算过程如图2-2所示。记视频序列中第n帧和第n1帧图像为fnfn1,两帧对应像素点的灰度值记为fn(x,y)fn1(x , y),按照式2.13将两帧图像对应像素点的灰度值进行相减,并取其绝对值,得到差分图像Dn

                                                                                      

        设定阈值T,按照式2.14逐个对像素点进行二值化处理,得到二值化图像Rn'。其中,灰度值为255的点即为前景(运动目标)点,灰度值为0的点即为背景点;对图像Rn'进行连通性分析,最终可得到含有完整运动目标的图像Rn

                                             

    2、三帧差分法

        两帧差分法适用于目标运动较为缓慢的场景,当运动较快时,由于目标在相邻帧图像上的位置相差较大,两帧图像相减后并不能得到完整的运动目标,因此,人们在两帧差分法的基础上提出了三帧差分法。

                

       三帧差分法的运算过程如图2-3所示。记视频序列中第n+1帧、第n帧和第n1帧的图像分别为fn+1fnfn1,三帧对应像素点的灰度值记为fn+1(x , y) fn(x , y) fn1(x , y) , 按照式2.13分别得到差分图像Dn+1Dn,对差分图像Dn+1Dn按照式2.15进行与操作,得到图像Dn',然后再进行阈值处理、连通性分析,最终提取出运动目标。 

                       

        在帧间差分法中,阈值 的选择非常重要。如果阈值T选取的值太小,则无法抑制差分图像中的噪声;如果阈值T选取的值太大,又有可能掩盖差分图像中目标的部分信息;而且固定的阈值T无法适应场景中光线变化等情况。为此,有人提出了在判决条件中加入对整体光照敏感的添加项的方法,将判决条件修改为:

                                   

        其中, N A为待检测区域中像素的总数目,λ为光照的抑制系数,A可设为整帧图像。添加项表达了整帧图像中光照的变化情况。如果场景中的光照变化较小,则该项的值趋向于零;如果场景中的光照变化明显,则该项的值明显增大,导致式2.16右侧判决条件自适应地增大,最终的判决结果为没有运动目标,这样就有效地抑制了光线变化对运动目标检测结果的影响。


    3、两帧差分和三帧差分的比较

        图 2-5 是采用帧间差分法对自拍序列 lab 序列进行运动目标检测的实验结果,(b)图是采用两帧差分法的检测结果,(c)图是采用三帧差分法的检测结果。lab序列中的目标运动较快,在这种情况下,运动目标在不同图像帧内的位置明显不同,采用两帧差分法检测出的目标会出现“重影”的现象,采用三帧差分法,可以检测出较为完整的运动目标。

                    

        综上所述,帧间差分法的原理简单,计算量小,能够快速检测出场景中的运动目标。但由实验结果可以看出,帧间差分法检测的目标不完整,内部含有“空洞”,这是因为运动目标在相邻帧之间的位置变化缓慢,目标内部在不同帧图像中相重叠的部分很难检测出来。帧间差分法通常不单独用在目标检测中,往往与其它的检测算法结合使用。







    展开全文
  • 运动检测 - 帧差法等原理

    千次阅读 2019-03-17 18:42:11
    大多数视频监控系统是摄像头固定的,因此静态背景下运动目标检测算法受到广泛关注,常用的方法有帧差法、光流法、背景减除法等。 1 帧差法的实现非常简单: 优点:实时性 缺点: 1、运动物体如果过大,且颜色...
  • 采用运动点团模式对鱼眼视频序列中的目标检测方法进行了研究和探讨。运动点团模式的运动目标检测分为三个层次,每个层次对应一个具体的检测算法,即基于像素层的背景提取和更新、运动点团层的点团检测和判定及运动...
  • 光流法 光流是指图像中模式运动的... 反之,如果图像中的目标发生运动,由于目标和图像背景存在相对运动,致使运动目标与邻域背景的速度矢量出现差异,进而实现运动目标检测。 光流法的前提假设: (1)相邻帧之间
  • 1 两通道DPCA动目标检测原理  PDCA(Plan-Do-Check-Act的简称)循环是品质管理循环,针对品质工作按规划、执行、查核与行动来进行活动,以确保可靠度目标之达成,并进而促使品质持续改善。规划(Plan):产品可靠度...
  • 式中, ω0为发射角频率, φ为初相;...如果目标固定不, 则距离R为常数。回波与发射信号之间有固定相位差ω0tr=2πf0·2R/c = (2π/λ) 2R, 它是电磁波往返于雷达与目标之间所产生的相位滞后。当目标...
  • 针对动态背景下运动目标检测问题,提出了一种基于对极几何约束的检测方法。该方法利用了视频序列中相继帧对应的背景角点满足对极几何约束条件这一原理,先提取前一帧的Harris角点,然后利用金字塔分层的Lucas-...
  • 在前面的文章中,已经介绍了基于SSD使用自己的数据训练目标检测模型(见文章:手把手教你训练自己的目标检测模型),本文将基于另一个目标检测模型YOLO,介绍如何使用自己的数据进行训练。 YOLO(You only look ...
  • 三分差分法 检测运动图像原理

    千次阅读 2009-06-09 17:57:00
    三分差分法检测运动图像原理作者:JeffNi 1.在动态图像中,取三帧图像,其中前一帧图像Fi-1(x,y),当前帧图像Fi(x, y),下一帧图像Fi+1(x,y). 2.将图象灰度化 3.计算当前帧与前一帧的差得前向帧差FDb(x,y). 4.计算下一帧...
  • 动态检测文献

    2013-09-30 20:31:39
    以某型机载平台的实际检测需求为出发点,在机载平台实验室条件下,进行跟踪误差、捕获性能等动态性能检测, 从理论上分析了以模拟...物目标仿真器(动态精度检测的核心测试设备)的工程化原理与设计,并进行了三维建模实践。
  • 在前面的文章中,已经介绍了基于SSD使用自己的数据训练目标检测模型(见文章:手把手教你训练自己的目标检测模型),本文将基于另一个目标检测模型YOLO,介绍如何使用自己的数据进行训练。YOLO(You only look once)是...
  • Lis3dh有两种工作方式,一种是其内置了多种算法来处理常见的应用场景(如静止检测、运动检测、屏幕翻转、失重、位置识别、单击和双击等等),用户只需简单配置算法对应的寄存器即可开始检测,一旦检测目标事件,...
  • Lis3dh有两种工作方式,一种是其内置了多种算法来处理常见的应用场景(如静止检测、运动检测、屏幕翻转、失重、位置识别、单击和双击等等),用户只需简单配置算法对应的寄存器即可开始检测,一旦检测目标事件,...
  • TLD运动检测目标跟踪详细介绍

    千次阅读 2017-04-17 20:43:27
    我主要会根据他在2010年发表的论文《Tracking-Learning-Detection》来分析TLD算法的原理。该项目的首页中有几段视频展示了TLD实时跟踪的效果和性能,其中的两个视频可以在这里下载:similar objects,human face。...
  • 主要目标 准备好Pytorch环境 了解目标检测的一些基本概念,包括目标框的两种表示形式,IoU等 下载好VOC数据集 ...熟悉目标检测基础原理,但需要巩固 笔记 用来表达bbox的格式通常有两种,(x1, y1, x
  • SSD训练自己的目标检测模型 ...在动手训练自己的目标检测模型之前,建议先了解一下目标检测模型的原理(见文章:大话目标检测经典模型RCNN、Fast RCNN、Faster RCNN,以及Mark R-CNN),这样才会更加清楚模型的训练...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 487
精华内容 194
关键字:

动目标检测原理