Video Segmentation ETSN

Abstract

关注两个问题:边界模糊与过度分割。

ETSN的第一步是Efficient Temporal Series Pyramid Networks(ETSPNet),能够捕捉局部和全局的逐帧特征并且提供精确的边界预测。

第二步是一种无监督的方法,称之为Local Burr Suppression(LBS),很大程度减少了过度分割的错误。

Introduction

第一个问题是边界的错误。这是因为标签变化是突然的,但是动作的转变是渐进的。

当前比较流行的解决方案是以提升感受野来建模(MS-TCN),以此来识别动作边界周围难以识别的帧。

MSTCN的缺陷在于高层中:1. 局部信息的损失;2. 长距离依赖关系的缺失。另外,只依赖基于长距离依赖的特征的话更会在边界周围的模糊帧上输出低置信度甚至错误的预测。

第二个问题是过度分割错误。当前的模型往往会给出错误的片段,由于视频中的噪声。

解决毛刺的方式目前有两种,分别是:平滑损失函数和全局平滑网络。

在这里插入图片描述ETSPNet使用了基于膨胀卷积的时间序列金字塔实现感受野的扩大,以此提高模糊帧的置信度。

我们认为毛刺只来源于局部的过度分割,所以提出了称之为LBS的后处理网络来定位和移除毛刺。

Technical approach

ETSPNet

只建立长距离的依赖导致细粒度信息的丢失以及预测错误边界。

在图像分割领域,采用金字塔的结构在识别图像分割边界。本文进行了方法的移植,在时间序列上使用金字塔结构。使得ETSPNet能捕获更精确的时间序列分割边界(说白了,就是在边界附近的逐帧准确率高了)。

第一层是一个1x1卷积来适应维度的变化,该层的输出是网络的起始特征。

在这里插入图片描述多层平行的卷积,膨胀因子不一样,卷积滤波器以及核大小是一样的。

之后再跟着激活函数ReLU以及1x1卷积(用于和起始特征保持一样的维度)。

为了精修初步的预测,我们使用了多阶段时间卷积网络的结构,但是每一阶段都采用了ETSPNet。

ETSPNet包含了多尺度的特征并且保留了输入序列的时间分辨率。

长期依赖区分相邻片段的类别,短期依赖识别边界。

class Single_ETSPNet(nn.Module):

    def __init__(self, in_channel, n_features, n_classes, n_layers):
        super().__init__()

        self.conv_in = nn.Conv1d(in_channel, n_features, 1)
        layers = [
            DilatedResidualLayer(2**i, n_features, n_features) for i in range(n_layers)]
        self.layers = nn.ModuleList(layers) 
        self.act = nn.PReLU(n_features*n_layers) # 针对连接后的特征维度的激活函数
        self.conv1_1 = nn.Conv1d(n_features*n_layers, n_features, 1) # 连接后的特征维度 —> 初始特征维度
        self.conv_out = nn.Conv1d(n_features, n_classes, 1) # 特征 -> 类别

    def forward(self, x):
            out = []
            # 初始特征
            in_feat = self.conv_in(x)
            # 如果out非空,那把左层的输出加给当前层的输入
            for layer in self.layers:
                out.append(layer(in_feat + out[-1] if len(out) != 0 else in_feat))
            # 连接并激活
            out_cat = self.act(torch.cat(out, dim=1))
            # 降维
            output = self.conv1_1(out_cat)
            # 输入与输出连接后输出分类结果
            output = self.conv_out(output + in_feat)
            return output

因为只使用四层卷积的话,对于一些困难帧会发生欠拟合的问题,所以ETSPNet将左层的输出加到了当前层的输入当中。

关于层内结构,用的还是MSTCN 的膨胀残差模块。

class DilatedResidualLayer(nn.Module):
    # Originally written by yabufarha
    # https://github.com/yabufarha/ms-tcn/blob/master/model.py

    def __init__(self, dilation, in_channel, out_channels):
        super().__init__()
        self.conv_dilated = nn.Conv1d(
            in_channel, out_channels, 3, padding=dilation, dilation=dilation)
        self.conv_in = nn.Conv1d(out_channels, out_channels, 1)
        self.dropout = nn.Dropout()

    def forward(self, x):
        out = F.relu(self.conv_dilated(x))
        out = self.conv_in(out)
        out = self.dropout(out)
        return x + out

ETSPNet之后是多层SSTCN,这也是依照的MSTCN++中提出的精修模块添加的,起到了平滑的作用。

class MultiStageTCN(nn.Module):

    def __init__(self, in_channel, n_classes, stages,
                 n_features=64, dilated_n_layers=10, kernel_size=15):
    
        super().__init__()
        if stages[0] == 'dilated':
            self.stage1 = SingleStageTCN(in_channel, n_features, n_classes, dilated_n_layers)
        elif stages[0] == 'etspnet':
            self.stage1 = Single_ETSPNet(in_channel, n_features, n_classes, dilated_n_layers) 
        elif stages[0] == 'ed':
            self.stage1 = EDTCN(in_channel, n_classes)
        else:
            print("Invalid values as stages in Mixed Multi Stage TCN")
            sys.exit(1)

        if len(stages) == 1:
            self.stages = None
        else:
            self.stages = []
            for stage in stages[1:]:
                if stage == 'dilated':
                    self.stages.append(SingleStageTCN(
                        n_classes, n_features, n_classes, dilated_n_layers))
                elif stage == 'ed':
                    self.stages.append(
                        EDTCN(n_classes, n_classes, kernel_size=kernel_size))
                else:
                    print("Invalid values as stages in Mixed Multi Stage TCN")
                    sys.exit(1)
            self.stages = nn.ModuleList(self.stages)

    def forward(self, x):

        if self.training:

            # # for training
            outputs = []
            out = self.stage1(x)
            outputs.append(out)
            
            if self.stages is not None:
                for stage in self.stages:
                    out = stage(F.softmax(out, dim=1))
                    outputs.append(out)
            return outputs
        else:

            # for evaluation
            out = self.stage1(x)
            if self.stages is not None:
                for stage in self.stages:
                    out = stage(F.softmax(out, dim=1))
            return out

Local Burr suppression

ETSPNet提升了这个分割的性能,但是没能够解决毛刺。

时间平滑损失函数(TMSE)人仍然会造成过度分割。BCN的LBP代价又太大了。

在这里插入图片描述LBS的前提是认为毛刺的来源是过度分割。LBS的灵感来源是NMS。

LBS分为两个步骤:

  1. 根据长度和平均置信度定位毛刺;
  2. 根据毛刺类型消除毛刺。

Locating the burrs

首先先得到片段的长度n,过于短的片段直接消除。

n ≤ L n\le L nL的片段列为可疑毛刺。

再根据平均置信度P,从可疑毛刺中选出待处理的毛刺。因为真实片段的高置信度,让LBS无法对他们下手。

Removing the burrs

更加连续毛刺的数量,分为连续毛刺和孤立毛刺。

在这里插入图片描述对于连续毛刺而言,我们首先认可他们之间的边界是成立的,因为信赖ETSPNet的边界预测能力。

于是,我们采用相邻的非毛刺片段来代替毛刺的类别。

对于奇数个连续的毛刺,忽视中间毛刺,将他们转化为偶数连续毛刺来处理。

对于孤立的毛刺,将其分为两个连续的毛刺(这个划分过程基于前后两个非毛刺片段的长度),然后执行偶数连续毛刺来处理。

视频分割是一种计算机视觉技术,旨在将视频分为不同的类别,如运动物体、背景等。视频分割的目标是检测视频中运动物体的运动轨迹,从而为行为识别、视频压缩、视频编辑等应用提供支持。本文将介绍视频分割的几种方法。 1. 基于背景分割的方法 基于背景分割的方法利用图像中的背景信息,并将运动物体与背景分开。这种方法的基本原理是,先对背景进行建模,然后将图像与背景模型对比,找到运动物体的区域。这种方法具有较低的计算成本和较高的准确性。 2. 基于移动物体分割的方法 基于移动物体分割的方法使用预定义的图像特征,如运动、颜色、纹理等,来检测运动物体。这种方法通过对图像像素强度的变化进行分析,找到物体的运动轨迹。这种方法具有较高的准确性和鲁棒性。 3. 基于深度学习的方法 基于深度学习的方法是近年来发展的一种新方法,它利用深度神经网络来自动学习不同类别的视频模式。这种方法可以通过大量的训练数据来训练模型,并可以精确定位和跟踪运动物体。 综上所述,视频分割是一种非常重要的计算机视觉技术,其方法包括基于背景分割、基于移动物体分割和基于深度学习的方法,不同的方法适用于不同的场景和应用。在未来,随着计算机视觉技术的不断发展,视频分割技术将发挥更重要的作用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

右边是我女神

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值