pwc细节

金字塔部分

 金字塔每层的通道数为:[16, 32, 64, 96, 128, 196],16为第一层,196为第6层。第一层分辨率最大,为输入图像尺寸的一半,之后每升高一层,分辨率变为上一层的一半。第6层分辨率最小。PWC一共6层金字塔。以输入图像为(256,448)为例子,那么第一层为(128,224),第6层为(4,7)

每层金字塔内部操作

第6层

先从第5层开始,也就是分辨率最低的开始,这一层的操作和其他层都不一样。第5层首先做一个corr,

corr = self.corr(c1[6], c2[6], 6)

然后直接预测

upfeat, flow = self.predict_flow(corr, None, None, None, 6)

然后把flow放一个列表里,用来计算这一层的loss

flow_pyr.append(flow)

最后上采样

up_flow = self.deconv(flow, 6, 'up_flow')
up_feat = self.deconv(upfeat, 6, 'up_feat')

5~3层

首先对上一层的光流值进行乘系数,然后在warp,这里的lvl=5,4,3,

scaler = 20. / 2**lvl  # scaler values are 0.625, 1.25, 2.5, 5.0
warp = self.warp(c2[lvl], up_flow * scaler, lvl)

然后做corr

corr = self.corr(c1[lvl], warp, lvl)

然后预测光流,这里的输入不光是cost volume,还有上一层上菜样之后的光流和特征

upfeat, flow = self.predict_flow(corr, c1[lvl], up_flow, up_feat, lvl)

第2层

这里最后不再对生成的光流进行上采样,而是对光流进行context处理,第二层的分辨率为(64,112),金字塔第一层我们不用。

flow = self.refine_flow(upfeat, flow, 2)
flow_pyr.append(flow)

上然上采样至输入图片分辨率,这里flow_pred_lvl=2,lvl_height为当前光流场的高.       不需要乘系数,下面有解释

scaler = 2**self.opts['flow_pred_lvl']
size = (lvl_height * scaler, lvl_width * scaler)
flow_pred = tf.image.resize_bilinear(flow, size, name="flow_pred") 

网络输出的的是每一层的光流和最终光流

return flow_pred, flow_pyr

计算LOSS

首先对光流真实值进行下采样,这里不需要乘以系数

scaled_flow_gt = tf.image.resize_bilinear(y, (lvl_height, lvl_width))
####scaled_flow_gt /= tf.cast(gt_height / lvl_height, dtype=tf.float32)

以最小分辨率为例,光流真实值的高为256,当前层的光流值的高为4,那么系数就是64.

norm = tf.norm(scaled_flow_gt - y_hat_pyr_lvl, ord=norm_order, axis=3) [8,4,7]
tf.reduce_sum(norm, axis=(1, 2)) [8]
level_loss = tf.reduce_mean(tf.reduce_sum(norm, axis=(1, 2))) []

维度从[8,,4,7]->[8]->[]

然后计算损失

total_loss += opts['alphas'][lvl] * tf.pow(level_loss + opts['epsilon'],1)

其中这里的系数为[0.32,   0.08,   0.02,    0.01,   0.005,    0.0025]

其中分辨率最低(也就是第6层)光流场的loss,对应0.32

最后需要注意,这一切都是建立在真实光流值除以20的情况下建立的,也就是做如下预处理。

scale_gt=gt/20

以第6层到第5层为例,warp需要把乘0.625,理由如下:

这是因为,第六层预测出来的光流场与scaled_flow_gt6非常接近(因为使用如下的损失函数),而scaled_flow_gt6与scale_gt的差距只有分辨率的差距。

layer {
  name: "loss6"
  type: "L1Loss"
  bottom: "predict_flow6"
  bottom: "scaled_flow_gt6"
  top: "loss6"
  loss_weight: 0.32
  l1_loss_param {
    l2_per_location: true
  }

因此,在第5层,需要用到光流场的时候,首先对第6层乘以20,那么就获得了正确的预测值,然后因为第5层的分辨率是输入的1/32,所以需要除以32,因此,20/32=0.625.就是这么来的

因此,其实金字塔的每一层输出的光流场乘以20之后,在放大分辨率都可以当成真实的光流场使用,其实金字塔就是一个不断细化的过程。

你可能感兴趣的:(pwc细节)