光流估计中cost volume详解

2024-01-30 20:59
文章标签 详解 volume 估计 cost 光流

本文主要是介绍光流估计中cost volume详解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原创声明:是暮涯啊 https://blog.csdn.net/longshaonihaoa/article/details/124726727

MEMC系列文章:
运动估计运动补偿(Motion estimation and motion compensation,MEMC)入门总结
深度学习MEMC插帧论文列表paper list
光流估计中cost volume详解
插帧中grid_sample函数详解

我认为之所以光流估计中会使用独有的cost volume,其初始形态是传统基于块的光流估计方法中,对每个前一帧图像F1中的某个块B1,计算其在一定范围内对应于后一帧图像2中哪个块B2最接近。假如B1的坐标为(x1,y1)B2的坐标为(x2,y2),对应这个块的光流矢量就是(x2-x1,y2-y1)。

1、FlowNet中的correlation

1.1 介绍

FlowNet作为光流估计的开山鼻祖,对correlation的计算花了大量篇幅。作者说这些分割啊,深度估计啊这些网络可以产生像素级预测,这说明NN用于得到像素级稠密光流估计是有可能的。那怎么涉及网络呢?一种是直接把前后帧图像F1F2堆叠后送到网络中,同时用GT的光流作为监督,让网络自己提取motion信息,也就是FlowNetSimple的结构。
原则上网络够大就行,但实际不确定行不行,所以退一步设计一个不那么通用,但效果好的网络。就先提取F1F2各自的有意义的特征,后来在将它们融合在一起。这大致类似于标准匹配方法,即首先从两个图像的块中提取特征,然后比较这些特征向量。接着就提出了灵魂疑问,怎么让网络计算特征间的相关性呢?
给定特征f1 f2,尺寸为WHC。correlation层计算f1的每个patch和f2的每个patch,现在只考虑f1中中心坐标为x1和f2中中心坐标为x2的两个patch之间的相关性。
请添加图片描述patch边长为K:=2k+1,该公式的定义就是一个卷积操作,只不过正常卷积使用filter卷data,这个使用其他data卷data。计算一个c(x1,x2)需要 c K 2 cK^2 cK2次乘操作(从这个计算量来看是per-channel操作),这还是一个点,如果计算全局就要 W 2 H 2 W^2H^2 W2H2次这样的操作。因此作者引入搜索范围和步长。对f2的搜索范围界定在D:=2d+1,x1和x2的步长分别为s1,s2。(这里其实就是传统快搜索里将全局搜索转为局部搜索),最后生成 [ W H D 2 ] [WHD^2] [WHD2] 的相关性矩阵。 D 2 D^2 D2意味着将patch间2D的相关性堆叠到一个维度。

1.2 代码实现

from spatial_correlation_sampler import SpatialCorrelationSampler
函数详细介绍可以看这里
更深一点想看c++的原始代码可以点这里 ,还是蛮标准的循环取点相乘再取平均。

2 PWCNet 里的cost Volume

2.1 介绍

PWCNet其实和SpyNet很像,都是金字塔,warp。但是PWCnet不同的地方有两个1)warp是对特征,2)就是我们这次介绍的主角cost volume。摘要对cost volume的介绍是:用warped 的特征和第一张图的特征计算构造一个cost volume,它被一个CNN处理用来估计光流。
相关工作中说 cost volume用于存储 像素与其相关联的下一帧的对应像素 的 数据匹配成本。在介绍网络结构时,作者使用特征计算匹配代价(matching cost),定义它为第一张图的特征和第二张图warp后的特征间的相关性(correlation)
请添加图片描述T为转置操作,N为列向量 c 1 l ( x 1 ) c_1^l(x_1) c1l(x1)的长度,上标l表示金字塔的第l层。作者认为对L层的金字塔,只需要计算很小的D个像素内的cost volume就好了,因为top层的一个像素的motion对应到最大尺度层就是 2 L − 1 2^{L-1} 2L1个像素了,因此可以把D设的很小。输出的结果是 [ D 2 H l W l ] [D^2H^lW^l] [D2HlWl],后两个表示l层feature map的宽高。
其实这里看计算和FlowNet的计算基本是相同的,都是对f1中的每个坐标(x,y)对应的特征向量与f2中坐标(x,y)周围范围d的特征向量计算匹配代价。区别在于FlowNet是逐通道计算两个patch间距离。PWCNet是逐WH计算特征向量间距离。这个向量间转置点乘的距离就是余弦相似度。如果FlowNet的步长=D,那理论上两者是相同的。
知乎有个对PWCnet中cost volume更仔细的介绍

2.2 代码实现

torch代码,代码来源

    def corr(self, refimg_fea, targetimg_fea):maxdisp=4b,c,h,w = refimg_fea.shape# 通过F.unfold取出f2的窗口范围d=2*maxdisp+1内的特征向量,# 这里由于F.unfold的步长默认为1,所以每个WH都能提取出周围d*d的特征向量,# 因此可以view到(b,c,2*maxdisp+1, 2*maxdisp+1,h,w)# ps:个人认为第二个 2*maxdisp+1**2 的 次方是 个错误,应也是2*maxdisp+1,但不影响targetimg_fea = F.unfold(targetimg_fea, (2*maxdisp+1,2*maxdisp+1), padding=maxdisp).view(b,c,2*maxdisp+1, 2*maxdisp+1**2,h,w)# 对f1扩维, ps: targetimg_fea后的view应该无效cost = refimg_fea.view(b,c,h,w)[:,:,np.newaxis, np.newaxis]*targetimg_fea.view(b,c,2*maxdisp+1, 2*maxdisp+1**2,h,w)cost = cost.sum(1)b, ph, pw, h, w = cost.size()cost = cost.view(b, ph * pw, h, w)/refimg_fea.size(1)return cost

下面这个代码虽然和上面一样,但我觉得更艺术,就贴下来了

def compute_cost_volume(feat1, feat2, param_dict):"""only implemented for:kernel_size = 1stride1 = 1stride2 = 1"""max_disp = param_dict["max_disp"]_, _, height, width = feat1.size()num_shifts = 2 * max_disp + 1feat2_padded = tf.pad(feat2, (max_disp, max_disp, max_disp, max_disp), "constant", 0)cost_list = []for i in range(num_shifts):for j in range(num_shifts):corr = torch.mean(feat1 * feat2_padded[:, :, i:(height + i), j:(width + j)], axis=1, keepdims=True)cost_list.append(corr)cost_volume = torch.cat(cost_list, axis=1)return cost_volume

3 LiteFlowNet中的correction

文章对这部分的介绍很少,只是说I1 I2间的点相关性通过高层特征向量间相关性计算得到。
请添加图片描述F1 F2 标傲世金字塔特征,d限制搜索范围,N表示特征向量长度。最后的代价矩阵c也会被集成到一个3D grid中。(其实和PWCNet的计算应该是相同的)

作者通过三个操作减少计算负担。1)每个特征level计算短距离匹配, 也就是限制d的大小,和PWC相同。2)通过f-warp拉进F1F2间特征空间距离。3)在高空间分辨率的level,只在采样点计算得到稀疏cost volume。然后对稀疏的cost volume进行空间方向的插值

4 MaskFlownet 中的cost volume

本文是对PWCnet的改进,核心就是一句话:做匹配代价容量计算时,应当排除那些在一帧中被遮挡的像素。
实现在于通过卷积预测mask后,将sigmoid(mask)与warp后的光流相乘。同时会加一个平衡项。该操作图示如下:
请添加图片描述
该操作对金字塔每层都实现一次,下面以第5层为例,代码实现如下:

warp5 = F.broadcast_mul(warp5, F.sigmoid(mask5)) + self.conv5f(tradeoff5)
warp5 = self.leakyRELU(warp5)
corr5 = self.corr(F, c15, warp5) 
corr5 = self.leakyRELU(corr5)

其中的相关性计算self.corr通过 F.Correlation 函数实现。但这个F是MXnet框架下的,详细介绍可以查看文档
文档中的相关性计算公式和FlowNet的完全相同。

5 RAFT 中 multi-scale 4D correlation volume

作者希望使用4D 金字塔 相关性 volume来计算视觉相似度(Visual Similarity)。其实现也更加简单,对图1的特征f1=[B C HW] 和 图2的特征f2=[B C H W] 直接点乘。也可以说就是将前面PWCnet的d设置为0,对应D=1,也就是只计算当前位置。 对应的f1中每个c与f2的HW个c相乘。
代码实现如下:

def corr(fmap1, fmap2):batch, dim, ht, wd = fmap1.shapefmap1 = fmap1.view(batch, dim, ht*wd)fmap2 = fmap2.view(batch, dim, ht*wd) # fimap转换维度后为(b,ht*wd,dim)*(b,dim,ht*wd)= (b,ht*wd, ht*wd)# 论文说的4D correlation volume 就是[h w h w]   corr = torch.matmul(fmap1.transpose(1,2), fmap2)corr = corr.view(batch, ht, wd, 1, ht, wd)return corr  / torch.sqrt(torch.tensor(dim).float())

6 总结

总的来说谈谈为什么计算光流的网络会有这个组件,我觉得一个是从传统方法延续过来的,可以采用coarse2fine的过程中逐渐指导下一层光流计算。另一个是说假如得到的d*d某个通道数值都很大,说明需要再往那个通道对应的运动向量移动。相当于嵌入了位置编码信息。但cost volume并非是计算光流所必需的,比如很早的SpyNet就没有使用该模块,毕竟计算cost volume的计算开销还是很大的。

以上如有错误请多多交流指正,创作不意,有用的话可以多多点赞收藏。

这篇关于光流估计中cost volume详解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Mysql 中的多表连接和连接类型详解

《Mysql中的多表连接和连接类型详解》这篇文章详细介绍了MySQL中的多表连接及其各种类型,包括内连接、左连接、右连接、全外连接、自连接和交叉连接,通过这些连接方式,可以将分散在不同表中的相关数据... 目录什么是多表连接?1. 内连接(INNER JOIN)2. 左连接(LEFT JOIN 或 LEFT

Java中switch-case结构的使用方法举例详解

《Java中switch-case结构的使用方法举例详解》:本文主要介绍Java中switch-case结构使用的相关资料,switch-case结构是Java中处理多个分支条件的一种有效方式,它... 目录前言一、switch-case结构的基本语法二、使用示例三、注意事项四、总结前言对于Java初学者

Linux内核之内核裁剪详解

《Linux内核之内核裁剪详解》Linux内核裁剪是通过移除不必要的功能和模块,调整配置参数来优化内核,以满足特定需求,裁剪的方法包括使用配置选项、模块化设计和优化配置参数,图形裁剪工具如makeme... 目录简介一、 裁剪的原因二、裁剪的方法三、图形裁剪工具四、操作说明五、make menuconfig

详解Java中的敏感信息处理

《详解Java中的敏感信息处理》平时开发中常常会遇到像用户的手机号、姓名、身份证等敏感信息需要处理,这篇文章主要为大家整理了一些常用的方法,希望对大家有所帮助... 目录前后端传输AES 对称加密RSA 非对称加密混合加密数据库加密MD5 + Salt/SHA + SaltAES 加密平时开发中遇到像用户的

Springboot使用RabbitMQ实现关闭超时订单(示例详解)

《Springboot使用RabbitMQ实现关闭超时订单(示例详解)》介绍了如何在SpringBoot项目中使用RabbitMQ实现订单的延时处理和超时关闭,通过配置RabbitMQ的交换机、队列和... 目录1.maven中引入rabbitmq的依赖:2.application.yml中进行rabbit

C语言线程池的常见实现方式详解

《C语言线程池的常见实现方式详解》本文介绍了如何使用C语言实现一个基本的线程池,线程池的实现包括工作线程、任务队列、任务调度、线程池的初始化、任务添加、销毁等步骤,感兴趣的朋友跟随小编一起看看吧... 目录1. 线程池的基本结构2. 线程池的实现步骤3. 线程池的核心数据结构4. 线程池的详细实现4.1 初

Python绘制土地利用和土地覆盖类型图示例详解

《Python绘制土地利用和土地覆盖类型图示例详解》本文介绍了如何使用Python绘制土地利用和土地覆盖类型图,并提供了详细的代码示例,通过安装所需的库,准备地理数据,使用geopandas和matp... 目录一、所需库的安装二、数据准备三、绘制土地利用和土地覆盖类型图四、代码解释五、其他可视化形式1.

SpringBoot使用Apache POI库读取Excel文件的操作详解

《SpringBoot使用ApachePOI库读取Excel文件的操作详解》在日常开发中,我们经常需要处理Excel文件中的数据,无论是从数据库导入数据、处理数据报表,还是批量生成数据,都可能会遇到... 目录项目背景依赖导入读取Excel模板的实现代码实现代码解析ExcelDemoInfoDTO 数据传输

如何用Java结合经纬度位置计算目标点的日出日落时间详解

《如何用Java结合经纬度位置计算目标点的日出日落时间详解》这篇文章主详细讲解了如何基于目标点的经纬度计算日出日落时间,提供了在线API和Java库两种计算方法,并通过实际案例展示了其应用,需要的朋友... 目录前言一、应用示例1、天安门升旗时间2、湖南省日出日落信息二、Java日出日落计算1、在线API2

使用Spring Cache时设置缓存键的注意事项详解

《使用SpringCache时设置缓存键的注意事项详解》在现代的Web应用中,缓存是提高系统性能和响应速度的重要手段之一,Spring框架提供了强大的缓存支持,通过​​@Cacheable​​、​​... 目录引言1. 缓存键的基本概念2. 默认缓存键生成器3. 自定义缓存键3.1 使用​​@Cacheab