Spaces:
Sleeping
Sleeping
from __future__ import absolute_import, division, print_function, unicode_literals | |
import os | |
import cv2 | |
import copy | |
import numpy as np | |
import scipy.io as sio | |
from tool.utils.common_utils import interp, BFconsistCheck, \ | |
FBconsistCheck, consistCheck, get_KeySourceFrame_flowNN_gradient | |
def get_flowNN_gradient(args, | |
gradient_x, | |
gradient_y, | |
mask_RGB, | |
mask, | |
videoFlowF, | |
videoFlowB, | |
videoNonLocalFlowF, | |
videoNonLocalFlowB): | |
# gradient_x: imgH x (imgW - 1 + 1) x 3 x nFrame | |
# gradient_y: (imgH - 1 + 1) x imgW x 3 x nFrame | |
# mask_RGB: imgH x imgW x nFrame | |
# mask: imgH x imgW x nFrame | |
# videoFlowF: imgH x imgW x 2 x (nFrame - 1) | [u, v] | |
# videoFlowB: imgH x imgW x 2 x (nFrame - 1) | [u, v] | |
# videoNonLocalFlowF: imgH x imgW x 2 x 3 x nFrame | |
# videoNonLocalFlowB: imgH x imgW x 2 x 3 x nFrame | |
if args.Nonlocal: | |
num_candidate = 5 | |
else: | |
num_candidate = 2 | |
imgH, imgW, nFrame = mask.shape | |
numPix = np.sum(mask) | |
# |--------------------| |--------------------| | |
# | y | | v | | |
# | x * | | u * | | |
# | | | | | |
# |--------------------| |--------------------| | |
# sub: numPix * 3 | [y, x, t] | |
# flowNN: numPix * 3 * 2 | [y, x, t], [BN, FN] | |
# HaveFlowNN: imgH * imgW * nFrame * 2 | |
# numPixInd: imgH * imgW * nFrame | |
# consistencyMap: imgH * imgW * 5 * nFrame | [BN, FN, NL2, NL3, NL4] | |
# consistency_uv: imgH * imgW * [BN, FN] * [u, v] * nFrame | |
# sub: numPix * [y, x, t] | position of mising pixels | |
sub = np.concatenate((np.where(mask == 1)[0].reshape(-1, 1), | |
np.where(mask == 1)[1].reshape(-1, 1), | |
np.where(mask == 1)[2].reshape(-1, 1)), axis=1) | |
# flowNN: numPix * [y, x, t] * [BN, FN] | flow neighbors | |
flowNN = np.ones((numPix, 3, 2)) * 99999 # * -1 | |
HaveFlowNN = np.ones((imgH, imgW, nFrame, 2)) * 99999 | |
HaveFlowNN[mask, :] = 0 | |
numPixInd = np.ones((imgH, imgW, nFrame)) * -1 | |
consistencyMap = np.zeros((imgH, imgW, num_candidate, nFrame)) | |
consistency_uv = np.zeros((imgH, imgW, 2, 2, nFrame)) | |
# numPixInd[y, x, t] gives the index of the missing pixel@[y, x, t] in sub, | |
# i.e. which row. numPixInd[y, x, t] = idx; sub[idx, :] = [y, x, t] | |
for idx in range(len(sub)): | |
numPixInd[sub[idx, 0], sub[idx, 1], sub[idx, 2]] = idx | |
# Initialization | |
frameIndSetF = range(1, nFrame) | |
frameIndSetB = range(nFrame - 2, -1, -1) | |
# 1. Forward Pass (backward flow propagation) | |
print('Forward Pass......') | |
NN_idx = 0 # BN:0 | |
for indFrame in frameIndSetF: | |
# Bool indicator of missing pixels at frame t | |
holepixPosInd = (sub[:, 2] == indFrame) | |
# Hole pixel location at frame t, i.e. [y, x, t] | |
holepixPos = sub[holepixPosInd, :] | |
# Calculate the backward flow neighbor. Should be located at frame t-1 | |
flowB_neighbor = copy.deepcopy(holepixPos) | |
flowB_neighbor = flowB_neighbor.astype(np.float32) | |
flowB_vertical = videoFlowB[:, :, 1, indFrame - 1] # t --> t-1 | |
flowB_horizont = videoFlowB[:, :, 0, indFrame - 1] | |
flowF_vertical = videoFlowF[:, :, 1, indFrame - 1] # t-1 --> t | |
flowF_horizont = videoFlowF[:, :, 0, indFrame - 1] | |
flowB_neighbor[:, 0] += flowB_vertical[holepixPos[:, 0], holepixPos[:, 1]] | |
flowB_neighbor[:, 1] += flowB_horizont[holepixPos[:, 0], holepixPos[:, 1]] | |
flowB_neighbor[:, 2] -= 1 | |
# Round the backward flow neighbor location | |
flow_neighbor_int = np.round(copy.deepcopy(flowB_neighbor)).astype(np.int32) | |
# Chen: I should combine the following two operations together | |
# Check the backward/forward consistency | |
IsConsist, _ = BFconsistCheck(flowB_neighbor, | |
flowF_vertical, | |
flowF_horizont, | |
holepixPos, | |
args.consistencyThres) | |
trueConsist = IsConsist[IsConsist == True] | |
BFdiff, BF_uv = consistCheck(videoFlowF[:, :, :, indFrame - 1], | |
videoFlowB[:, :, :, indFrame - 1]) | |
# Check out-of-boundary | |
# Last column and last row does not have valid gradient | |
ValidPos = np.logical_and( | |
np.logical_and(flow_neighbor_int[:, 0] >= 0, | |
flow_neighbor_int[:, 0] < imgH - 1), | |
np.logical_and(flow_neighbor_int[:, 1] >= 0, | |
flow_neighbor_int[:, 1] < imgW - 1)) | |
# Only work with pixels that are not out-of-boundary | |
holepixPos = holepixPos[ValidPos, :] | |
flowB_neighbor = flowB_neighbor[ValidPos, :] | |
flow_neighbor_int = flow_neighbor_int[ValidPos, :] | |
IsConsist = IsConsist[ValidPos] | |
# For each missing pixel in holepixPos|[y, x, t], | |
# we check its backward flow neighbor flowB_neighbor|[y', x', t-1]. | |
# Case 1: If mask[round(y'), round(x'), t-1] == 0, | |
# the backward flow neighbor of [y, x, t] is known. | |
# [y', x', t-1] is the backward flow neighbor. | |
# KnownInd: Among all backward flow neighbors, which pixel is known. | |
KnownInd = mask[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame - 1] == 0 | |
KnownIsConsist = np.logical_and(KnownInd, IsConsist) | |
holepixPos_valid = holepixPos[KnownIsConsist] | |
# We save backward flow neighbor flowB_neighbor in flowNN | |
flowNN[numPixInd[holepixPos[KnownIsConsist, 0], | |
holepixPos[KnownIsConsist, 1], | |
indFrame].astype(np.int32), :, NN_idx] = \ | |
flowB_neighbor[KnownIsConsist, :] | |
# flowNN[np.where(holepixPosInd == 1)[0][ValidPos][KnownIsConsist], :, 0] = \ | |
# flowB_neighbor[KnownIsConsist, :] | |
# We mark [y, x, t] in HaveFlowNN as 1 | |
HaveFlowNN[holepixPos[KnownIsConsist, 0], | |
holepixPos[KnownIsConsist, 1], | |
indFrame, | |
NN_idx] = 1 | |
# HaveFlowNN[:, :, :, 0] | |
# 0: Backward flow neighbor can not be reached | |
# 1: Backward flow neighbor can be reached | |
# -1: Pixels that do not need to be completed | |
consistency_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], NN_idx, 0, indFrame] = np.abs(BF_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], 0]) | |
consistency_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], NN_idx, 1, indFrame] = np.abs(BF_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], 1]) | |
# Case 2: If mask[round(y'), round(x'), t-1] == 1, | |
# the pixel@[round(y'), round(x'), t-1] is also occluded. | |
# We further check if we already assign a backward flow neighbor for the backward flow neighbor | |
# If HaveFlowNN[round(y'), round(x'), t-1] == 0, | |
# this is isolated pixel. Do nothing. | |
# If HaveFlowNN[round(y'), round(x'), t-1] == 1, | |
# we can borrow the value and refine it. | |
UnknownInd = np.invert(KnownInd) | |
# If we already assign a backward flow neighbor@[round(y'), round(x'), t-1] | |
HaveNNInd = HaveFlowNN[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame - 1, | |
NN_idx] == 1 | |
# Unknown & IsConsist & HaveNNInd | |
Valid_ = np.logical_and.reduce((UnknownInd, HaveNNInd, IsConsist)) | |
refineVec = np.concatenate(( | |
(flowB_neighbor[:, 0] - flow_neighbor_int[:, 0]).reshape(-1, 1), | |
(flowB_neighbor[:, 1] - flow_neighbor_int[:, 1]).reshape(-1, 1), | |
np.zeros((flowB_neighbor[:, 0].shape[0])).reshape(-1, 1)), 1) | |
# Check if the transitive backward flow neighbor of [y, x, t] is known. | |
# Sometimes after refinement, it is no longer known. | |
flowNN_tmp = copy.deepcopy(flowNN[numPixInd[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame - 1].astype(np.int32), :, NN_idx] + refineVec[:, :]) | |
flowNN_tmp = np.round(flowNN_tmp).astype(np.int32) | |
# Check out-of-boundary. flowNN_tmp may be out-of-boundary | |
ValidPos_ = np.logical_and( | |
np.logical_and(flowNN_tmp[:, 0] >= 0, | |
flowNN_tmp[:, 0] < imgH - 1), | |
np.logical_and(flowNN_tmp[:, 1] >= 0, | |
flowNN_tmp[:, 1] < imgW - 1)) | |
# Change the out-of-boundary value to 0, in order to run mask[y,x,t] | |
# in the next line. It won't affect anything as ValidPos_ is saved already | |
flowNN_tmp[np.invert(ValidPos_), :] = 0 | |
ValidNN = mask[flowNN_tmp[:, 0], | |
flowNN_tmp[:, 1], | |
flowNN_tmp[:, 2]] == 0 | |
# Valid = np.logical_and.reduce((Valid_, ValidNN, ValidPos_)) | |
Valid = np.logical_and.reduce((Valid_, ValidPos_)) | |
# We save the transitive backward flow neighbor flowB_neighbor in flowNN | |
flowNN[numPixInd[holepixPos[Valid, 0], | |
holepixPos[Valid, 1], | |
indFrame].astype(np.int32), :, NN_idx] = \ | |
flowNN[numPixInd[flow_neighbor_int[Valid, 0], | |
flow_neighbor_int[Valid, 1], | |
indFrame - 1].astype(np.int32), :, NN_idx] + refineVec[Valid, :] | |
# We mark [y, x, t] in HaveFlowNN as 1 | |
HaveFlowNN[holepixPos[Valid, 0], | |
holepixPos[Valid, 1], | |
indFrame, | |
NN_idx] = 1 | |
consistency_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], NN_idx, 0, indFrame] = np.maximum(np.abs(BF_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], 0]), np.abs(consistency_uv[flow_neighbor_int[Valid, 0], flow_neighbor_int[Valid, 1], NN_idx, 0, indFrame - 1])) | |
consistency_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], NN_idx, 1, indFrame] = np.maximum(np.abs(BF_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], 1]), np.abs(consistency_uv[flow_neighbor_int[Valid, 0], flow_neighbor_int[Valid, 1], NN_idx, 1, indFrame - 1])) | |
consistencyMap[:, :, NN_idx, indFrame] = (consistency_uv[:, :, NN_idx, 0, indFrame] ** 2 + consistency_uv[:, :, NN_idx, 1, indFrame] ** 2) ** 0.5 | |
print("Frame {0:3d}: {1:8d} + {2:8d} = {3:8d}" | |
.format(indFrame, | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] == 1), | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] == 0), | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] != 99999))) | |
# 2. Backward Pass (forward flow propagation) | |
print('Backward Pass......') | |
NN_idx = 1 # FN:1 | |
for indFrame in frameIndSetB: | |
# Bool indicator of missing pixels at frame t | |
holepixPosInd = (sub[:, 2] == indFrame) | |
# Hole pixel location at frame t, i.e. [y, x, t] | |
holepixPos = sub[holepixPosInd, :] | |
# Calculate the forward flow neighbor. Should be located at frame t+1 | |
flowF_neighbor = copy.deepcopy(holepixPos) | |
flowF_neighbor = flowF_neighbor.astype(np.float32) | |
flowF_vertical = videoFlowF[:, :, 1, indFrame] # t --> t+1 | |
flowF_horizont = videoFlowF[:, :, 0, indFrame] | |
flowB_vertical = videoFlowB[:, :, 1, indFrame] # t+1 --> t | |
flowB_horizont = videoFlowB[:, :, 0, indFrame] | |
flowF_neighbor[:, 0] += flowF_vertical[holepixPos[:, 0], holepixPos[:, 1]] | |
flowF_neighbor[:, 1] += flowF_horizont[holepixPos[:, 0], holepixPos[:, 1]] | |
flowF_neighbor[:, 2] += 1 | |
# Round the forward flow neighbor location | |
flow_neighbor_int = np.round(copy.deepcopy(flowF_neighbor)).astype(np.int32) | |
# Check the forawrd/backward consistency | |
IsConsist, _ = FBconsistCheck(flowF_neighbor, | |
flowB_vertical, | |
flowB_horizont, | |
holepixPos, | |
args.consistencyThres) | |
FBdiff, FB_uv = consistCheck(videoFlowB[:, :, :, indFrame], | |
videoFlowF[:, :, :, indFrame]) | |
# Check out-of-boundary | |
# Last column and last row does not have valid gradient | |
ValidPos = np.logical_and( | |
np.logical_and(flow_neighbor_int[:, 0] >= 0, | |
flow_neighbor_int[:, 0] < imgH - 1), | |
np.logical_and(flow_neighbor_int[:, 1] >= 0, | |
flow_neighbor_int[:, 1] < imgW - 1)) | |
# Only work with pixels that are not out-of-boundary | |
holepixPos = holepixPos[ValidPos, :] | |
flowF_neighbor = flowF_neighbor[ValidPos, :] | |
flow_neighbor_int = flow_neighbor_int[ValidPos, :] | |
IsConsist = IsConsist[ValidPos] | |
# Case 1: | |
KnownInd = mask[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame + 1] == 0 | |
KnownIsConsist = np.logical_and(KnownInd, IsConsist) | |
flowNN[numPixInd[holepixPos[KnownIsConsist, 0], | |
holepixPos[KnownIsConsist, 1], | |
indFrame].astype(np.int32), :, NN_idx] = \ | |
flowF_neighbor[KnownIsConsist, :] | |
HaveFlowNN[holepixPos[KnownIsConsist, 0], | |
holepixPos[KnownIsConsist, 1], | |
indFrame, | |
NN_idx] = 1 | |
consistency_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], NN_idx, 0, indFrame] = np.abs(FB_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], 0]) | |
consistency_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], NN_idx, 1, indFrame] = np.abs(FB_uv[holepixPos[KnownIsConsist, 0], holepixPos[KnownIsConsist, 1], 1]) | |
# Case 2: | |
UnknownInd = np.invert(KnownInd) | |
HaveNNInd = HaveFlowNN[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame + 1, | |
NN_idx] == 1 | |
# Unknown & IsConsist & HaveNNInd | |
Valid_ = np.logical_and.reduce((UnknownInd, HaveNNInd, IsConsist)) | |
refineVec = np.concatenate(( | |
(flowF_neighbor[:, 0] - flow_neighbor_int[:, 0]).reshape(-1, 1), | |
(flowF_neighbor[:, 1] - flow_neighbor_int[:, 1]).reshape(-1, 1), | |
np.zeros((flowF_neighbor[:, 0].shape[0])).reshape(-1, 1)), 1) | |
# Check if the transitive backward flow neighbor of [y, x, t] is known. | |
# Sometimes after refinement, it is no longer known. | |
flowNN_tmp = copy.deepcopy(flowNN[numPixInd[flow_neighbor_int[:, 0], | |
flow_neighbor_int[:, 1], | |
indFrame + 1].astype(np.int32), :, NN_idx] + refineVec[:, :]) | |
flowNN_tmp = np.round(flowNN_tmp).astype(np.int32) | |
# Check out-of-boundary. flowNN_tmp may be out-of-boundary | |
ValidPos_ = np.logical_and( | |
np.logical_and(flowNN_tmp[:, 0] >= 0, | |
flowNN_tmp[:, 0] < imgH - 1), | |
np.logical_and(flowNN_tmp[:, 1] >= 0, | |
flowNN_tmp[:, 1] < imgW - 1)) | |
# Change the out-of-boundary value to 0, in order to run mask[y,x,t] | |
# in the next line. It won't affect anything as ValidPos_ is saved already | |
flowNN_tmp[np.invert(ValidPos_), :] = 0 | |
ValidNN = mask[flowNN_tmp[:, 0], | |
flowNN_tmp[:, 1], | |
flowNN_tmp[:, 2]] == 0 | |
# Valid = np.logical_and.reduce((Valid_, ValidNN, ValidPos_)) | |
Valid = np.logical_and.reduce((Valid_, ValidPos_)) | |
# We save the transitive backward flow neighbor flowB_neighbor in flowNN | |
flowNN[numPixInd[holepixPos[Valid, 0], | |
holepixPos[Valid, 1], | |
indFrame].astype(np.int32), :, NN_idx] = \ | |
flowNN[numPixInd[flow_neighbor_int[Valid, 0], | |
flow_neighbor_int[Valid, 1], | |
indFrame + 1].astype(np.int32), :, NN_idx] + refineVec[Valid, :] | |
# We mark [y, x, t] in HaveFlowNN as 1 | |
HaveFlowNN[holepixPos[Valid, 0], | |
holepixPos[Valid, 1], | |
indFrame, | |
NN_idx] = 1 | |
consistency_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], NN_idx, 0, indFrame] = np.maximum(np.abs(FB_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], 0]), np.abs(consistency_uv[flow_neighbor_int[Valid, 0], flow_neighbor_int[Valid, 1], NN_idx, 0, indFrame + 1])) | |
consistency_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], NN_idx, 1, indFrame] = np.maximum(np.abs(FB_uv[holepixPos[Valid, 0], holepixPos[Valid, 1], 1]), np.abs(consistency_uv[flow_neighbor_int[Valid, 0], flow_neighbor_int[Valid, 1], NN_idx, 1, indFrame + 1])) | |
consistencyMap[:, :, NN_idx, indFrame] = (consistency_uv[:, :, NN_idx, 0, indFrame] ** 2 + consistency_uv[:, :, NN_idx, 1, indFrame] ** 2) ** 0.5 | |
print("Frame {0:3d}: {1:8d} + {2:8d} = {3:8d}" | |
.format(indFrame, | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] == 1), | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] == 0), | |
np.sum(HaveFlowNN[:, :, indFrame, NN_idx] != 99999))) | |
# Interpolation | |
gradient_x_BN = copy.deepcopy(gradient_x) | |
gradient_y_BN = copy.deepcopy(gradient_y) | |
gradient_x_FN = copy.deepcopy(gradient_x) | |
gradient_y_FN = copy.deepcopy(gradient_y) | |
for indFrame in range(nFrame): | |
# Index of missing pixel whose backward flow neighbor is from frame indFrame | |
SourceFmInd = np.where(flowNN[:, 2, 0] == indFrame) | |
print("{0:8d} pixels are from source Frame {1:3d}" | |
.format(len(SourceFmInd[0]), indFrame)) | |
# The location of the missing pixel whose backward flow neighbor is | |
# from frame indFrame flowNN[SourceFmInd, 0, 0], flowNN[SourceFmInd, 1, 0] | |
if len(SourceFmInd[0]) != 0: | |
# |--------------------| | |
# | y | | |
# | x * | | |
# | | | |
# |--------------------| | |
# sub: numPix x 3 [y, x, t] | |
# img: [y, x] | |
# interp(img, x, y) | |
gradient_x_BN[sub[SourceFmInd[0], :][:, 0], | |
sub[SourceFmInd[0], :][:, 1], | |
:, sub[SourceFmInd[0], :][:, 2]] = \ | |
interp(gradient_x_BN[:, :, :, indFrame], | |
flowNN[SourceFmInd, 1, 0].reshape(-1), | |
flowNN[SourceFmInd, 0, 0].reshape(-1)) | |
gradient_y_BN[sub[SourceFmInd[0], :][:, 0], | |
sub[SourceFmInd[0], :][:, 1], | |
:, sub[SourceFmInd[0], :][:, 2]] = \ | |
interp(gradient_y_BN[:, :, :, indFrame], | |
flowNN[SourceFmInd, 1, 0].reshape(-1), | |
flowNN[SourceFmInd, 0, 0].reshape(-1)) | |
assert(((sub[SourceFmInd[0], :][:, 2] - indFrame) <= 0).sum() == 0) | |
for indFrame in range(nFrame - 1, -1, -1): | |
# Index of missing pixel whose forward flow neighbor is from frame indFrame | |
SourceFmInd = np.where(flowNN[:, 2, 1] == indFrame) | |
print("{0:8d} pixels are from source Frame {1:3d}" | |
.format(len(SourceFmInd[0]), indFrame)) | |
if len(SourceFmInd[0]) != 0: | |
gradient_x_FN[sub[SourceFmInd[0], :][:, 0], | |
sub[SourceFmInd[0], :][:, 1], | |
:, sub[SourceFmInd[0], :][:, 2]] = \ | |
interp(gradient_x_FN[:, :, :, indFrame], | |
flowNN[SourceFmInd, 1, 1].reshape(-1), | |
flowNN[SourceFmInd, 0, 1].reshape(-1)) | |
gradient_y_FN[sub[SourceFmInd[0], :][:, 0], | |
sub[SourceFmInd[0], :][:, 1], | |
:, sub[SourceFmInd[0], :][:, 2]] = \ | |
interp(gradient_y_FN[:, :, :, indFrame], | |
flowNN[SourceFmInd, 1, 1].reshape(-1), | |
flowNN[SourceFmInd, 0, 1].reshape(-1)) | |
assert(((indFrame - sub[SourceFmInd[0], :][:, 2]) <= 0).sum() == 0) | |
# New mask | |
mask_tofill = np.zeros((imgH, imgW, nFrame)).astype(np.bool) | |
for indFrame in range(nFrame): | |
if args.Nonlocal: | |
consistencyMap[:, :, 2, indFrame], _ = consistCheck( | |
videoNonLocalFlowB[:, :, :, 0, indFrame], | |
videoNonLocalFlowF[:, :, :, 0, indFrame]) | |
consistencyMap[:, :, 3, indFrame], _ = consistCheck( | |
videoNonLocalFlowB[:, :, :, 1, indFrame], | |
videoNonLocalFlowF[:, :, :, 1, indFrame]) | |
consistencyMap[:, :, 4, indFrame], _ = consistCheck( | |
videoNonLocalFlowB[:, :, :, 2, indFrame], | |
videoNonLocalFlowF[:, :, :, 2, indFrame]) | |
HaveNN = np.zeros((imgH, imgW, num_candidate)) | |
if args.Nonlocal: | |
HaveKeySourceFrameFlowNN, gradient_x_KeySourceFrameFlowNN, gradient_y_KeySourceFrameFlowNN = \ | |
get_KeySourceFrame_flowNN_gradient(sub, | |
indFrame, | |
mask, | |
videoNonLocalFlowB, | |
videoNonLocalFlowF, | |
gradient_x, | |
gradient_y, | |
args.consistencyThres) | |
HaveNN[:, :, 2] = HaveKeySourceFrameFlowNN[:, :, 0] == 1 | |
HaveNN[:, :, 3] = HaveKeySourceFrameFlowNN[:, :, 1] == 1 | |
HaveNN[:, :, 4] = HaveKeySourceFrameFlowNN[:, :, 2] == 1 | |
HaveNN[:, :, 0] = HaveFlowNN[:, :, indFrame, 0] == 1 | |
HaveNN[:, :, 1] = HaveFlowNN[:, :, indFrame, 1] == 1 | |
NotHaveNN = np.logical_and(np.invert(HaveNN.astype(np.bool)), | |
np.repeat(np.expand_dims((mask[:, :, indFrame]), 2), num_candidate, axis=2)) | |
if args.Nonlocal: | |
HaveNN_sum = np.logical_or.reduce((HaveNN[:, :, 0], | |
HaveNN[:, :, 1], | |
HaveNN[:, :, 2], | |
HaveNN[:, :, 3], | |
HaveNN[:, :, 4])) | |
else: | |
HaveNN_sum = np.logical_or.reduce((HaveNN[:, :, 0], | |
HaveNN[:, :, 1])) | |
gradient_x_Candidate = np.zeros((imgH, imgW, 3, num_candidate)) | |
gradient_y_Candidate = np.zeros((imgH, imgW, 3, num_candidate)) | |
gradient_x_Candidate[:, :, :, 0] = gradient_x_BN[:, :, :, indFrame] | |
gradient_y_Candidate[:, :, :, 0] = gradient_y_BN[:, :, :, indFrame] | |
gradient_x_Candidate[:, :, :, 1] = gradient_x_FN[:, :, :, indFrame] | |
gradient_y_Candidate[:, :, :, 1] = gradient_y_FN[:, :, :, indFrame] | |
if args.Nonlocal: | |
gradient_x_Candidate[:, :, :, 2] = gradient_x_KeySourceFrameFlowNN[:, :, :, 0] | |
gradient_y_Candidate[:, :, :, 2] = gradient_y_KeySourceFrameFlowNN[:, :, :, 0] | |
gradient_x_Candidate[:, :, :, 3] = gradient_x_KeySourceFrameFlowNN[:, :, :, 1] | |
gradient_y_Candidate[:, :, :, 3] = gradient_y_KeySourceFrameFlowNN[:, :, :, 1] | |
gradient_x_Candidate[:, :, :, 4] = gradient_x_KeySourceFrameFlowNN[:, :, :, 2] | |
gradient_y_Candidate[:, :, :, 4] = gradient_y_KeySourceFrameFlowNN[:, :, :, 2] | |
consistencyMap[:, :, :, indFrame] = np.exp( - consistencyMap[:, :, :, indFrame] / args.alpha) | |
consistencyMap[NotHaveNN[:, :, 0], 0, indFrame] = 0 | |
consistencyMap[NotHaveNN[:, :, 1], 1, indFrame] = 0 | |
if args.Nonlocal: | |
consistencyMap[NotHaveNN[:, :, 2], 2, indFrame] = 0 | |
consistencyMap[NotHaveNN[:, :, 3], 3, indFrame] = 0 | |
consistencyMap[NotHaveNN[:, :, 4], 4, indFrame] = 0 | |
weights = (consistencyMap[HaveNN_sum, :, indFrame] * HaveNN[HaveNN_sum, :]) / ((consistencyMap[HaveNN_sum, :, indFrame] * HaveNN[HaveNN_sum, :]).sum(axis=1, keepdims=True)) | |
# Fix the numerical issue. 0 / 0 | |
fix = np.where((consistencyMap[HaveNN_sum, :, indFrame] * HaveNN[HaveNN_sum, :]).sum(axis=1, keepdims=True) == 0)[0] | |
weights[fix, :] = HaveNN[HaveNN_sum, :][fix, :] / HaveNN[HaveNN_sum, :][fix, :].sum(axis=1, keepdims=True) | |
# Fuse RGB channel independently | |
gradient_x[HaveNN_sum, 0, indFrame] = \ | |
np.sum(np.multiply(gradient_x_Candidate[HaveNN_sum, 0, :], weights), axis=1) | |
gradient_x[HaveNN_sum, 1, indFrame] = \ | |
np.sum(np.multiply(gradient_x_Candidate[HaveNN_sum, 1, :], weights), axis=1) | |
gradient_x[HaveNN_sum, 2, indFrame] = \ | |
np.sum(np.multiply(gradient_x_Candidate[HaveNN_sum, 2, :], weights), axis=1) | |
gradient_y[HaveNN_sum, 0, indFrame] = \ | |
np.sum(np.multiply(gradient_y_Candidate[HaveNN_sum, 0, :], weights), axis=1) | |
gradient_y[HaveNN_sum, 1, indFrame] = \ | |
np.sum(np.multiply(gradient_y_Candidate[HaveNN_sum, 1, :], weights), axis=1) | |
gradient_y[HaveNN_sum, 2, indFrame] = \ | |
np.sum(np.multiply(gradient_y_Candidate[HaveNN_sum, 2, :], weights), axis=1) | |
mask_tofill[np.logical_and(np.invert(HaveNN_sum), mask[:, :, indFrame]), indFrame] = True | |
return gradient_x, gradient_y, mask_tofill | |