Closed Serge-weihao closed 3 years ago
Hi, the implementation of this function is adopted from GCA-Matting, which I suppose is based on the official Matlab evaluation code.
You can evaluate the real-world portrait dataset using the "Whole Image" score, or you can modify to support the detail map in the real-world portrait dataset (e.g., detail_map[detail_map>0] = 128). Sorry for being busy these days, I will also update the code to give better support later.
does evaluation on real-world portrait also use metrics divided by 1000?
Yes, same metrics are used in real-world portrait dataset
Are your Trimap computed on "unknown" and TrimapFG computed on "Whole Image"?
Hi, in this table. TrimapFG and Trimap refers to different types of inputs to our model. Since DIM dataset only provides trimap as guidance inputs, we use it to simulate a rough segmentation mask in two ways: TrimapFG: we only use the definite foreground region of the trimap; Trimap: we use a soft version of trrimap (i.e. trimap / 255.0). You can refer to our paper or code for more details :)
thanks for updating, i will solve them with your code. But one more question, does self._noupdate_u_v() updating your network weight during evaluation?
class SpectralNorm(nn.Module):
"""
Based on https://github.com/heykeetae/Self-Attention-GAN/blob/master/spectral.py
and add _noupdate_u_v() for evaluation
"""
def __init__(self, module, name='weight', power_iterations=1):
super(SpectralNorm, self).__init__()
self.module = module
self.name = name
self.power_iterations = power_iterations
if not self._made_params():
self._make_params()
def _update_u_v(self):
u = getattr(self.module, self.name + "_u")
v = getattr(self.module, self.name + "_v")
w = getattr(self.module, self.name + "_bar")
height = w.data.shape[0]
for _ in range(self.power_iterations):
v.data = l2normalize(torch.mv(torch.t(w.view(height,-1).data), u.data))
u.data = l2normalize(torch.mv(w.view(height,-1).data, v.data))
sigma = u.dot(w.view(height, -1).mv(v))
setattr(self.module, self.name, w / sigma.expand_as(w))
def _noupdate_u_v(self):
u = getattr(self.module, self.name + "_u")
v = getattr(self.module, self.name + "_v")
w = getattr(self.module, self.name + "_bar")
height = w.data.shape[0]
sigma = u.dot(w.view(height, -1).mv(v))
setattr(self.module, self.name, w / sigma.expand_as(w))
def _made_params(self):
try:
u = getattr(self.module, self.name + "_u")
v = getattr(self.module, self.name + "_v")
w = getattr(self.module, self.name + "_bar")
return True
except AttributeError:
return False
def _make_params(self):
w = getattr(self.module, self.name)
height = w.data.shape[0]
width = w.view(height, -1).data.shape[1]
u = Parameter(w.data.new(height).normal_(0, 1), requires_grad=False)
v = Parameter(w.data.new(width).normal_(0, 1), requires_grad=False)
u.data = l2normalize(u.data)
v.data = l2normalize(v.data)
w_bar = Parameter(w.data)
del self.module._parameters[self.name]
self.module.register_parameter(self.name + "_u", u)
self.module.register_parameter(self.name + "_v", v)
self.module.register_parameter(self.name + "_bar", w_bar)
def forward(self, *args):
# if torch.is_grad_enabled() and self.module.training:
if self.module.training:
self._update_u_v()
else:
self._noupdate_u_v()
return self.module.forward(*args)
thanks for updating, i will solve them with your code. But one more question, does self._noupdate_u_v() updating your network weight during evaluation?
class SpectralNorm(nn.Module): """ Based on https://github.com/heykeetae/Self-Attention-GAN/blob/master/spectral.py and add _noupdate_u_v() for evaluation """ def __init__(self, module, name='weight', power_iterations=1): super(SpectralNorm, self).__init__() self.module = module self.name = name self.power_iterations = power_iterations if not self._made_params(): self._make_params() def _update_u_v(self): u = getattr(self.module, self.name + "_u") v = getattr(self.module, self.name + "_v") w = getattr(self.module, self.name + "_bar") height = w.data.shape[0] for _ in range(self.power_iterations): v.data = l2normalize(torch.mv(torch.t(w.view(height,-1).data), u.data)) u.data = l2normalize(torch.mv(w.view(height,-1).data, v.data)) sigma = u.dot(w.view(height, -1).mv(v)) setattr(self.module, self.name, w / sigma.expand_as(w)) def _noupdate_u_v(self): u = getattr(self.module, self.name + "_u") v = getattr(self.module, self.name + "_v") w = getattr(self.module, self.name + "_bar") height = w.data.shape[0] sigma = u.dot(w.view(height, -1).mv(v)) setattr(self.module, self.name, w / sigma.expand_as(w)) def _made_params(self): try: u = getattr(self.module, self.name + "_u") v = getattr(self.module, self.name + "_v") w = getattr(self.module, self.name + "_bar") return True except AttributeError: return False def _make_params(self): w = getattr(self.module, self.name) height = w.data.shape[0] width = w.view(height, -1).data.shape[1] u = Parameter(w.data.new(height).normal_(0, 1), requires_grad=False) v = Parameter(w.data.new(width).normal_(0, 1), requires_grad=False) u.data = l2normalize(u.data) v.data = l2normalize(v.data) w_bar = Parameter(w.data) del self.module._parameters[self.name] self.module.register_parameter(self.name + "_u", u) self.module.register_parameter(self.name + "_v", v) self.module.register_parameter(self.name + "_bar", w_bar) def forward(self, *args): # if torch.is_grad_enabled() and self.module.training: if self.module.training: self._update_u_v() else: self._noupdate_u_v() return self.module.forward(*args)
ok, it does not change the weight after eval forward
https://github.com/yucornetto/MGMatting/blob/671678dc16a6a856632946865af88eea76c5fcf5/code-base/utils/evaluate.py#L102 and can the code evaluates real-world portrait dataset? https://github.com/yucornetto/MGMatting/blob/main/code-base/evaluation.py