如何使用光流和 grid_sample 扭曲图像?

Posted

技术标签:

【中文标题】如何使用光流和 grid_sample 扭曲图像?【英文标题】:How to warp the image with optical flow and grid_sample? 【发布时间】:2020-02-29 13:37:05 【问题描述】:

我有一些关于光流图像变形的问题。

我想通过 grid_sample 测试扭曲图像,并且我从 PWC-Net 获得了样本(两个带有流的图像),如下所示: 从 --> https://github.com/NVlabs/PWC-Net/tree/master/PyTorch/data 输入图像 来自 --> https://github.com/NVlabs/PWC-Net/tree/master/PyTorch/tmp

的流文件

result image

input image 1

input image 2

import torch
import torch.nn as nn
import torch.nn.functional as F
import cv2
import numpy as np
from imageio import imread

def warp(x, flo):
“”"
warp an image/tensor (im2) back to im1, according to the optical flow

x: [B, C, H, W] (im2)
flo: [B, 2, H, W] flow

"""
B, C, H, W = x.size()
# mesh grid
xx = torch.arange(0, W).view(1 ,-1).repeat(H ,1)
yy = torch.arange(0, H).view(-1 ,1).repeat(1 ,W)
xx = xx.view(1 ,1 ,H ,W).repeat(B ,1 ,1 ,1)
yy = yy.view(1 ,1 ,H ,W).repeat(B ,1 ,1 ,1)
grid = torch.cat((xx ,yy) ,1).float()

if x.is_cuda:
    grid = grid.cuda()
vgrid = Variable(grid) + flo

# scale grid to [-1,1]
vgrid[: ,0 ,: ,:] = 2.0 *vgrid[: ,0 ,: ,:].clone() / max( W -1 ,1 ) -1.0
vgrid[: ,1 ,: ,:] = 2.0 *vgrid[: ,1 ,: ,:].clone() / max( H -1 ,1 ) -1.0

vgrid = vgrid.permute(0 ,2 ,3 ,1)
flo = flo.permute(0 ,2 ,3 ,1)
output = F.grid_sample(x, vgrid)
mask = torch.autograd.Variable(torch.ones(x.size())).cuda()
mask = F.grid_sample(mask, vgrid)

mask[mask <0.9999] = 0
mask[mask >0] = 1

return output*mask
test = cv2.readOpticalFlow(‘reference_frame_0010.flo’)
test = torch.from_numpy(test)
test = test.view(1, 2, H, W)
test = Variable(test).cuda()

test_img2 = cv2.imread(‘frame_0011.png’)
test_img2 = torch.from_numpy(test_img2)
test_img2 = test_img2.view(1, 3, H, W)
test_img2 = Variable(test_img2).cuda()

out = warp(test_img2, test)
out = out.view(H, W, 3)
out = out.cpu()
out = np.float32(out)
cv2.imwrite(‘test3.png’, out*255)

我已经运行了上面的代码并得到了结果图像。正如你所看到的最后一张图片,这不是我所期望的。 看起来像带有网格的图像的几个部分。 使用光流获得扭曲的目标图像是否正确? 如果不是,我怎样才能让整个图像看起来像输入的彩色图像?

请帮我解决这个问题。

【问题讨论】:

【参考方案1】:

用opencv加载图像时,它的形状为[height, width, 3]

当您尝试使用重塑它时

test_img2 = test_img2.view(1, 3, H, W)

它混合了所有的值,而不是仅仅交换尺寸。你需要的是torch.transpose函数。

test_img2 = test_img2.transpose(2, 0, 1)[None]

这里[None] 添加了批次维度。

【讨论】:

以上是关于如何使用光流和 grid_sample 扭曲图像?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用光流图像将后一帧扭曲到前一帧

如何将光流场(浮点数)映射到像素数据(字符)以进行图像变形?

cv2 Farneback 光流值太低

如何使用javascript修复HTML画布对象中的扭曲/扭曲和剪切图像?

如何在opencv中使用光流跟踪来分割图像?

如何计算光流的时间导数