光流 GMA : Learning to Estimate Hidden Motions with Global Motion Aggregation

本文主要是介绍光流 GMA : Learning to Estimate Hidden Motions with Global Motion Aggregation,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

GMA的架构

在这里插入图片描述
        文中的的全局运动聚合(GMA)模块包含在阴影框中,这是RAFT的一个独立附加模块,具有较低的计算开销,可显著提高性能。它将视觉上下文特征和运动特征作为输入,并输出聚合的运动特征,这些特征在整个图像中共享信息。然后将这些聚合的全局运动特征与局部运动特征和视觉上下文特征连接起来,由GRU解码为剩余流。这使网络能够根据特定像素位置的需要,灵活地选择或组合局部和全局运动特征。例如,局部图像证据较差的位置(例如由遮挡引起)可能会优先考虑全局运动特征。GMA的详细示意图如下图所示:
在这里插入图片描述

RAFT

R A F T : { 编码层:从两个输入图像中提取每像素特征的特征编码器,以及仅从 I 1 中提取特征的上下文编码器。 相关层 : 通过取所有特征向量对的内积来构造 4 D W × H × W × H 相关矩阵。 4 D 体积的最后 2 维在多个尺度上汇集,以构建多尺度信息。 一种更新算子,通过使用当前估计值从 4 D 相关矩阵集合中查找值,反复更新光流。 RAFT: \left\{\begin{array}{l}编码层:从两个输入图像中提取每像素特征的特征编码器,以及仅从I_1中提取特征的上下文编码器。\\ 相关层:通过取所有特征向量对的内积来构造4D W×H×W×H相关矩阵。4D体积的最后2维在多个尺度上汇集,以构建多尺度信息。\\ 一种更新算子,通过使用当前估计值从4D相关矩阵集合中查找值,反复更新光流。 \end{array}\right. RAFT: 编码层:从两个输入图像中提取每像素特征的特征编码器,以及仅从I1中提取特征的上下文编码器。相关层:通过取所有特征向量对的内积来构造4DW×H×W×H相关矩阵。4D体积的最后2维在多个尺度上汇集,以构建多尺度信息。一种更新算子,通过使用当前估计值从4D相关矩阵集合中查找值,反复更新光流。

在这里插入图片描述

GMA的论文观点

在这里插入图片描述
        Geoffrey Hinton在1976年的第一篇论文中写道,“必须通过找到最佳的全球解释来解决局部歧义”[13]。这种想法在现代深度学习时代仍然适用。为了解决遮挡造成的歧义,我们的核心思想是允许网络在更高的层次上推理,也就是说,在隐式推理了哪些像素在外观特征空间中是相似的之后,全局聚合相似像素的运动特征。我们假设,通过在参考框架中寻找具有相似外观的点,网络将能够找到具有相似运动的点。这是因为观察到单个物体上的点的运动通常是均匀的。例如,向右奔跑的人的运动向量向右偏移,即使我们看不到该人的大部分由于遮挡而在匹配帧中结束的位置,也会保持这种偏移。我们可以使用这种统计偏差将运动信息从高(隐式)置信度的非遮挡像素传播到低置信度的遮挡像素。这里,置信度可以解释为是否存在明显的匹配,即在正确的位移处存在高相关值。
        有了这些想法,我们从transformers网络中获得了灵感,transformers网络以其建模长期依赖性的能力而闻名。与transformers中的自我注意机制不同,在transformers中,查询、键和值来自相同的特征向量,我们使用了一种广义的注意变体。我们的查询和关键特征是上下文特征图的投影,用于建模第1帧中的外观自相似性。值特征是运动特征的投影,运动特征本身就是4D相关体积的编码。根据查询和关键特征计算出的注意矩阵用于聚合作为运动隐藏表示的值特征。我们将其命名为全局运动聚合(GMA)模块。聚合后的运动特征与局部运动特征以及背景特征连接起来,由GRU解码。GMA的详细示意图如图4所示。

代码与链接

        可以直接运行demo的命令进行官方提供的demo的测试,经过读取数据,调整大小,计算光流:

python evaluate_single.py --model checkpoints/gma-sintel.pth --path imgs
def load_image(imfile): # 'imgs\\frame_0047.png' img = np.array(Image.open(imfile)).astype(np.uint8) # (436, 1024, 3)img = torch.from_numpy(img).permute(2, 0, 1).float() # torch.Size([3, 436, 1024])return img[None].to(DEVICE)# torch.Size([1, 3, 436, 1024])
padder = InputPadder(image1.shape)
image1, image2 = padder.pad(image1, image2)
flow_low, flow_up = model(image1, image2, iters=12, test_mode=True)
# torch.Size([1, 2, 55, 128])  torch.Size([1, 2, 440, 1024])

在这里插入图片描述

        The overall code framework is adapted from RAFT. We thank the authors for the contribution. We also thank Phil Wang for open-sourcing transformer implementations.
        整个代码框架改编自RAFT。我们感谢作者的贡献。我们还感谢Phil Wang开放源代码转换器的实现。

网络结构:

RAFTGMA((fnet): BasicEncoder((norm1): InstanceNorm2d(64, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))(relu1): ReLU(inplace=True)(layer1): Sequential((0): ResidualBlock((conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(64, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(64, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False))(1): ResidualBlock((conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(64, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(64, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)))(layer2): Sequential((0): ResidualBlock((conv1): Conv2d(64, 96, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(conv2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm3): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(downsample): Sequential((0): Conv2d(64, 96, kernel_size=(1, 1), stride=(2, 2))(1): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)))(1): ResidualBlock((conv1): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(96, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)))(layer3): Sequential((0): ResidualBlock((conv1): Conv2d(96, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm3): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(downsample): Sequential((0): Conv2d(96, 128, kernel_size=(1, 1), stride=(2, 2))(1): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)))(1): ResidualBlock((conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)(norm2): InstanceNorm2d(128, eps=1e-05, momentum=0.1, affine=False, track_running_stats=False)))(conv2): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1)))(cnet): BasicEncoder((norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(conv1): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3))(relu1): ReLU(inplace=True)(layer1): Sequential((0): ResidualBlock((conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(1): ResidualBlock((conv1): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(layer2): Sequential((0): ResidualBlock((conv1): Conv2d(64, 96, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(conv2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm3): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(downsample): Sequential((0): Conv2d(64, 96, kernel_size=(1, 1), stride=(2, 2))(1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((conv1): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(96, 96, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(96, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(layer3): Sequential((0): ResidualBlock((conv1): Conv2d(96, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1))(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm3): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(downsample): Sequential((0): Conv2d(96, 128, kernel_size=(1, 1), stride=(2, 2))(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((conv1): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True)(norm1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(norm2): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(conv2): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1)))(update_block): GMAUpdateBlock((encoder): BasicMotionEncoder((convc1): Conv2d(324, 256, kernel_size=(1, 1), stride=(1, 1))(convc2): Conv2d(256, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(convf1): Conv2d(2, 128, kernel_size=(7, 7), stride=(1, 1), padding=(3, 3))(convf2): Conv2d(128, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv): Conv2d(256, 126, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)))(gru): SepConvGRU((convz1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convr1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convq1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convz2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))(convr2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))(convq2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0)))(flow_head): FlowHead((conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(256, 2, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True))(mask): Sequential((0): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(256, 576, kernel_size=(1, 1), stride=(1, 1)))(aggregator): Aggregate((to_v): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False)))(att): Attention((to_qk): Conv2d(128, 256, kernel_size=(1, 1), stride=(1, 1), bias=False)(pos_emb): RelPosEmb((rel_height): Embedding(319, 128)(rel_width): Embedding(319, 128)))
)
GMAUpdateBlock((encoder): BasicMotionEncoder((convc1): Conv2d(324, 256, kernel_size=(1, 1), stride=(1, 1))(convc2): Conv2d(256, 192, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(convf1): Conv2d(2, 128, kernel_size=(7, 7), stride=(1, 1), padding=(3, 3))(convf2): Conv2d(128, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv): Conv2d(256, 126, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)))(gru): SepConvGRU((convz1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convr1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convq1): Conv2d(512, 128, kernel_size=(1, 5), stride=(1, 1), padding=(0, 2))(convz2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))(convr2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0))(convq2): Conv2d(512, 128, kernel_size=(5, 1), stride=(1, 1), padding=(2, 0)))(flow_head): FlowHead((conv1): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(conv2): Conv2d(256, 2, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(relu): ReLU(inplace=True))(mask): Sequential((0): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))(1): ReLU(inplace=True)(2): Conv2d(256, 576, kernel_size=(1, 1), stride=(1, 1)))(aggregator): Aggregate((to_v): Conv2d(128, 128, kernel_size=(1, 1), stride=(1, 1), bias=False))
)
 [RAFT论文](https://arxiv.org/abs/2003.12039)[GMA论文](https://arxiv.org/pdf/2104.02409.pdf)[官方代码实现](https://github.com/zacjiang/GMA)[视频讲解](https://www.bilibili.com/video/BV1tM4y1T7kk?)

这篇关于光流 GMA : Learning to Estimate Hidden Motions with Global Motion Aggregation的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/292201

相关文章

简单的Q-learning|小明的一维世界(3)

简单的Q-learning|小明的一维世界(1) 简单的Q-learning|小明的一维世界(2) 一维的加速度世界 这个世界,小明只能控制自己的加速度,并且只能对加速度进行如下三种操作:增加1、减少1、或者不变。所以行动空间为: { u 1 = − 1 , u 2 = 0 , u 3 = 1 } \{u_1=-1, u_2=0, u_3=1\} {u1​=−1,u2​=0,u3​=1}

简单的Q-learning|小明的一维世界(2)

上篇介绍了小明的一维世界模型 、Q-learning的状态空间、行动空间、奖励函数、Q-table、Q table更新公式、以及从Q值导出策略的公式等。最后给出最简单的一维位置世界的Q-learning例子,从给出其状态空间、行动空间、以及稠密与稀疏两种奖励函数的设置方式。下面将继续深入,GO! 一维的速度世界 这个世界,小明只能控制自己的速度,并且只能对速度进行如下三种操作:增加1、减

关于OceanBase MySQL 模式中全局索引 global index 的常见问题

在OceanBase的问答区和开源社区钉钉群聊中,时常会有关于全局索引 global index的诸多提问,因此,借这篇博客,针对其中一些普遍出现的问题进行简要的解答。 什么是 global index ? 由于 MySQL 不具备 global index 的概念,因此这一问题会经常被社区版用户提及。就在前几天,就要人询问下面这个语法的意义。 create table part_tes

Learning Memory-guided Normality for Anomaly Detection——学习记忆引导的常态异常检测

又是一篇在自编码器框架中研究使用记忆模块的论文,可以看做19年的iccv的论文的衍生,在我的博客中对19年iccv这篇论文也做了简单介绍。韩国人写的,应该是吧,这名字听起来就像。 摘要abstract 我们解决异常检测的问题,即检测视频序列中的异常事件。基于卷积神经网络的异常检测方法通常利用代理任务(如重建输入视频帧)来学习描述正常情况的模型,而在训练时看不到异常样本,并在测试时使用重建误

Learning Temporal Regularity in Video Sequences——视频序列的时间规则性学习

Learning Temporal Regularity in Video Sequences CVPR2016 无监督视频异常事件检测早期工作 摘要 由于对“有意义”的定义不明确以及场景混乱,因此在较长的视频序列中感知有意义的活动是一个具有挑战性的问题。我们通过在非常有限的监督下使用多种来源学习常规运动模式的生成模型(称为规律性)来解决此问题。体来说,我们提出了两种基于自动编码器的方法,以

COD论文笔记 Adaptive Guidance Learning for Camouflaged Object Detection

论文的主要动机、现有方法的不足、拟解决的问题、主要贡献和创新点如下: 动机: 论文的核心动机是解决伪装目标检测(COD)中的挑战性任务。伪装目标检测旨在识别和分割那些在视觉上与周围环境高度相似的目标,这对于计算机视觉来说是非常困难的任务。尽管深度学习方法在该领域取得了一定进展,但现有方法仍面临有效分离目标和背景的难题,尤其是在伪装目标与背景特征高度相似的情况下。 现有方法的不足之处: 过于

One-Shot Imitation Learning

发表时间:NIPS2017 论文链接:https://readpaper.com/pdf-annotate/note?pdfId=4557560538297540609&noteId=2424799047081637376 作者单位:Berkeley AI Research Lab, Work done while at OpenAI Yan Duan†§ , Marcin Andrychow

Introduction to Deep Learning with PyTorch

1、Introduction to PyTorch, a Deep Learning Library 1.1、Importing PyTorch and related packages import torch# supports:## image data with torchvision## audio data with torchaudio## text data with t

《Learning To Count Everything》CVPR2021

摘要 论文提出了一种新的方法来解决视觉计数问题,即在给定类别中仅有少量标注实例的情况下,对任何类别的对象进行计数。将计数问题视为一个少样本回归任务,并提出了一种新颖的方法,该方法通过查询图像和查询图像中的少量示例对象来预测图像中所有感兴趣对象的存在密度图。此外,还提出了一种新颖的适应策略,使网络能够在测试时仅使用新类别中的少量示例对象来适应任何新的视觉类别。为了支持这一任务,作者还引入了一个包含

One-Shot Imitation Learning with Invariance Matching for Robotic Manipulation

发表时间:5 Jun 2024 论文链接:https://readpaper.com/pdf-annotate/note?pdfId=2408639872513958656&noteId=2408640378699078912 作者单位:Rutgers University Motivation:学习一个通用的policy,可以执行一组不同的操作任务,是机器人技术中一个有前途的新方向。然而,