|
import torch |
|
from util.image_pool import ImagePool |
|
from .base_model import BaseModel |
|
from . import networks |
|
import os |
|
import math |
|
|
|
W = 11 |
|
aa = int(math.floor(512./W)) |
|
res = 512 - W*aa |
|
|
|
|
|
def padpart(A,part,centers,opt,device): |
|
IMAGE_SIZE = opt.fineSize |
|
bs,nc,_,_ = A.shape |
|
ratio = IMAGE_SIZE / 256 |
|
NOSE_W = opt.NOSE_W * ratio |
|
NOSE_H = opt.NOSE_H * ratio |
|
EYE_W = opt.EYE_W * ratio |
|
EYE_H = opt.EYE_H * ratio |
|
MOUTH_W = opt.MOUTH_W * ratio |
|
MOUTH_H = opt.MOUTH_H * ratio |
|
A_p = torch.ones((bs,nc,IMAGE_SIZE,IMAGE_SIZE)).to(device) |
|
padvalue = -1 |
|
for i in range(bs): |
|
center = centers[i] |
|
if part == 'nose': |
|
A_p[i] = torch.nn.ConstantPad2d((center[2,0] - NOSE_W / 2, IMAGE_SIZE - (center[2,0]+NOSE_W/2), center[2,1] - NOSE_H / 2, IMAGE_SIZE - (center[2,1]+NOSE_H/2)),padvalue)(A[i]) |
|
elif part == 'eyel': |
|
A_p[i] = torch.nn.ConstantPad2d((center[0,0] - EYE_W / 2, IMAGE_SIZE - (center[0,0]+EYE_W/2), center[0,1] - EYE_H / 2, IMAGE_SIZE - (center[0,1]+EYE_H/2)),padvalue)(A[i]) |
|
elif part == 'eyer': |
|
A_p[i] = torch.nn.ConstantPad2d((center[1,0] - EYE_W / 2, IMAGE_SIZE - (center[1,0]+EYE_W/2), center[1,1] - EYE_H / 2, IMAGE_SIZE - (center[1,1]+EYE_H/2)),padvalue)(A[i]) |
|
elif part == 'mouth': |
|
A_p[i] = torch.nn.ConstantPad2d((center[3,0] - MOUTH_W / 2, IMAGE_SIZE - (center[3,0]+MOUTH_W/2), center[3,1] - MOUTH_H / 2, IMAGE_SIZE - (center[3,1]+MOUTH_H/2)),padvalue)(A[i]) |
|
return A_p |
|
|
|
import numpy as np |
|
def nonlinearDt(dt,type='atan',xmax=torch.Tensor([10.0])): |
|
if type == 'atan': |
|
nldt = torch.atan(dt*xmax) / torch.atan(xmax) |
|
elif type == 'sigmoid': |
|
nldt = (torch.sigmoid(dt*xmax)-0.5) / (torch.sigmoid(xmax)-0.5) |
|
elif type == 'tanh': |
|
nldt = torch.tanh(dt*xmax) / torch.tanh(xmax) |
|
elif type == 'pow': |
|
nldt = torch.pow(dt*xmax,2) / torch.pow(xmax,2) |
|
elif type == 'exp': |
|
if xmax.item()>1: |
|
xmax = xmax / 3 |
|
nldt = (torch.exp(dt*xmax)-1) / (torch.exp(xmax)-1) |
|
|
|
return nldt |
|
|
|
class APDrawingPPStyleModel(BaseModel): |
|
def name(self): |
|
return 'APDrawingPPStyleModel' |
|
|
|
@staticmethod |
|
def modify_commandline_options(parser, is_train=True): |
|
|
|
|
|
|
|
parser.set_defaults(pool_size=0, no_lsgan=True, norm='batch') |
|
parser.set_defaults(dataset_mode='aligned') |
|
parser.set_defaults(auxiliary_root='auxiliaryeye2o') |
|
parser.set_defaults(use_local=True, hair_local=True, bg_local=True) |
|
parser.set_defaults(discriminator_local=True, gan_loss_strategy=2) |
|
parser.set_defaults(chamfer_loss=True, dt_nonlinear='exp', lambda_chamfer=0.35, lambda_chamfer2=0.35) |
|
parser.set_defaults(nose_ae=True, others_ae=True, compactmask=True, MOUTH_H=56) |
|
parser.set_defaults(soft_border=1, batch_size=1, save_epoch_freq=25) |
|
parser.add_argument('--nnG_hairc', type=int, default=6, help='nnG for hair classifier') |
|
parser.add_argument('--use_resnet', action='store_true', help='use resnet for generator') |
|
parser.add_argument('--regarch', type=int, default=4, help='architecture for netRegressor') |
|
if is_train: |
|
parser.add_argument('--lambda_L1', type=float, default=100.0, help='weight for L1 loss') |
|
parser.add_argument('--lambda_local', type=float, default=25.0, help='weight for Local loss') |
|
parser.set_defaults(netG_dt='unet_512') |
|
parser.set_defaults(netG_line='unet_512') |
|
|
|
return parser |
|
|
|
def initialize(self, opt): |
|
BaseModel.initialize(self, opt) |
|
self.isTrain = opt.isTrain |
|
|
|
self.loss_names = ['G_GAN', 'G_L1', 'D_real', 'D_fake'] |
|
if self.isTrain and self.opt.no_l1_loss: |
|
self.loss_names = ['G_GAN', 'D_real', 'D_fake'] |
|
if self.isTrain and self.opt.use_local and not self.opt.no_G_local_loss: |
|
self.loss_names.append('G_local') |
|
self.loss_names.append('G_hair_local') |
|
self.loss_names.append('G_bg_local') |
|
if self.isTrain and self.opt.discriminator_local: |
|
self.loss_names.append('D_real_local') |
|
self.loss_names.append('D_fake_local') |
|
self.loss_names.append('G_GAN_local') |
|
if self.isTrain and self.opt.chamfer_loss: |
|
self.loss_names.append('G_chamfer') |
|
self.loss_names.append('G_chamfer2') |
|
if self.isTrain and self.opt.continuity_loss: |
|
self.loss_names.append('G_continuity') |
|
self.loss_names.append('G') |
|
print('loss_names', self.loss_names) |
|
|
|
self.visual_names = ['real_A', 'fake_B', 'real_B'] |
|
if self.opt.use_local: |
|
self.visual_names += ['fake_B0', 'fake_B1'] |
|
self.visual_names += ['fake_B_hair', 'real_B_hair', 'real_A_hair'] |
|
self.visual_names += ['fake_B_bg', 'real_B_bg', 'real_A_bg'] |
|
if self.opt.region_enm in [0,1]: |
|
if self.opt.nose_ae: |
|
self.visual_names += ['fake_B_nose_v','fake_B_nose_v1','fake_B_nose_v2','cmask1no'] |
|
if self.opt.others_ae: |
|
self.visual_names += ['fake_B_eyel_v','fake_B_eyel_v1','fake_B_eyel_v2','cmask1el'] |
|
self.visual_names += ['fake_B_eyer_v','fake_B_eyer_v1','fake_B_eyer_v2','cmask1er'] |
|
self.visual_names += ['fake_B_mouth_v','fake_B_mouth_v1','fake_B_mouth_v2','cmask1mo'] |
|
elif self.opt.region_enm in [2]: |
|
self.visual_names += ['fake_B_nose','fake_B_eyel','fake_B_eyer','fake_B_mouth'] |
|
if self.isTrain and self.opt.chamfer_loss: |
|
self.visual_names += ['dt1', 'dt2'] |
|
self.visual_names += ['dt1gt', 'dt2gt'] |
|
if self.isTrain and self.opt.soft_border: |
|
self.visual_names += ['mask'] |
|
if not self.isTrain and self.opt.save2: |
|
self.visual_names = ['real_A', 'fake_B'] |
|
print('visuals', self.visual_names) |
|
|
|
self.auxiliary_model_names = [] |
|
if self.isTrain: |
|
self.model_names = ['G', 'D'] |
|
if self.opt.discriminator_local: |
|
self.model_names += ['DLEyel','DLEyer','DLNose','DLMouth','DLHair','DLBG'] |
|
|
|
if self.opt.chamfer_loss: |
|
self.auxiliary_model_names += ['DT1', 'DT2'] |
|
self.auxiliary_model_names += ['Line1', 'Line2'] |
|
if self.opt.continuity_loss: |
|
self.auxiliary_model_names += ['Regressor'] |
|
else: |
|
self.model_names = ['G'] |
|
if self.opt.test_continuity_loss: |
|
self.auxiliary_model_names += ['Regressor'] |
|
if self.opt.use_local: |
|
self.model_names += ['GLEyel','GLEyer','GLNose','GLMouth','GLHair','GLBG','GCombine'] |
|
self.auxiliary_model_names += ['CLm','CLh'] |
|
|
|
if self.opt.nose_ae: |
|
self.auxiliary_model_names += ['AE'] |
|
if self.opt.others_ae: |
|
self.auxiliary_model_names += ['AEel','AEer','AEmowhite','AEmoblack'] |
|
print('model_names', self.model_names) |
|
print('auxiliary_model_names', self.auxiliary_model_names) |
|
|
|
self.netG = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, opt.netG, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
opt.nnG) |
|
print('netG', opt.netG) |
|
|
|
if self.isTrain: |
|
use_sigmoid = opt.no_lsgan |
|
self.netD = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
print('netD', opt.netD, opt.n_layers_D) |
|
if self.opt.discriminator_local: |
|
self.netDLEyel = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
self.netDLEyer = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
self.netDLNose = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
self.netDLMouth = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
self.netDLHair = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
self.netDLBG = networks.define_D(opt.input_nc + opt.output_nc, opt.ndf, opt.netD, |
|
opt.n_layers_D, opt.norm, use_sigmoid, opt.init_type, opt.init_gain, self.gpu_ids) |
|
|
|
|
|
if self.opt.use_local: |
|
netlocal1 = 'partunet' if self.opt.use_resnet == 0 else 'resnet_nblocks' |
|
netlocal2 = 'partunet2' if self.opt.use_resnet == 0 else 'resnet_6blocks' |
|
netlocal2_style = 'partunet2style' if self.opt.use_resnet == 0 else 'resnet_style2_6blocks' |
|
self.netGLEyel = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal1, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=3) |
|
self.netGLEyer = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal1, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=3) |
|
self.netGLNose = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal1, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=3) |
|
self.netGLMouth = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal1, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=3) |
|
self.netGLHair = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal2_style, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=4, |
|
extra_channel=3) |
|
self.netGLBG = networks.define_G(opt.input_nc, opt.output_nc, opt.ngf, netlocal2, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, nnG=4) |
|
|
|
print('combiner_type', self.opt.combiner_type) |
|
self.netGCombine = networks.define_G(2*opt.output_nc, opt.output_nc, opt.ngf, self.opt.combiner_type, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, 2) |
|
|
|
ratio = self.opt.fineSize / 256 |
|
self.MOUTH_H = int(self.opt.MOUTH_H * ratio) |
|
self.MOUTH_W = int(self.opt.MOUTH_W * ratio) |
|
self.netCLm = networks.define_G(opt.input_nc, 2, opt.ngf, 'classifier', opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
nnG = 3, ae_h = self.MOUTH_H, ae_w = self.MOUTH_W) |
|
self.netCLh = networks.define_G(opt.input_nc, 3, opt.ngf, 'classifier', opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
nnG = opt.nnG_hairc, ae_h = opt.fineSize, ae_w = opt.fineSize) |
|
|
|
|
|
if self.isTrain: |
|
self.fake_AB_pool = ImagePool(opt.pool_size) |
|
|
|
self.criterionGAN = networks.GANLoss(use_lsgan=not opt.no_lsgan).to(self.device) |
|
self.criterionL1 = torch.nn.L1Loss() |
|
|
|
|
|
self.optimizers = [] |
|
if not self.opt.use_local: |
|
print('G_params 1 components') |
|
self.optimizer_G = torch.optim.Adam(self.netG.parameters(), |
|
lr=opt.lr, betas=(opt.beta1, 0.999)) |
|
else: |
|
G_params = list(self.netG.parameters()) + list(self.netGLEyel.parameters()) + list(self.netGLEyer.parameters()) + list(self.netGLNose.parameters()) + list(self.netGLMouth.parameters()) + list(self.netGCombine.parameters()) + list(self.netGLHair.parameters()) + list(self.netGLBG.parameters()) |
|
print('G_params 8 components') |
|
self.optimizer_G = torch.optim.Adam(G_params, |
|
lr=opt.lr, betas=(opt.beta1, 0.999)) |
|
|
|
if not self.opt.discriminator_local: |
|
print('D_params 1 components') |
|
self.optimizer_D = torch.optim.Adam(self.netD.parameters(), |
|
lr=opt.lr, betas=(opt.beta1, 0.999)) |
|
else: |
|
D_params = list(self.netD.parameters()) + list(self.netDLEyel.parameters()) +list(self.netDLEyer.parameters()) + list(self.netDLNose.parameters()) + list(self.netDLMouth.parameters()) + list(self.netDLHair.parameters()) + list(self.netDLBG.parameters()) |
|
print('D_params 7 components') |
|
self.optimizer_D = torch.optim.Adam(D_params, |
|
lr=opt.lr, betas=(opt.beta1, 0.999)) |
|
self.optimizers.append(self.optimizer_G) |
|
self.optimizers.append(self.optimizer_D) |
|
|
|
|
|
if self.opt.use_local and self.opt.nose_ae: |
|
ratio = self.opt.fineSize / 256 |
|
NOSE_H = self.opt.NOSE_H * ratio |
|
NOSE_W = self.opt.NOSE_W * ratio |
|
self.netAE = networks.define_G(opt.output_nc, opt.output_nc, opt.ngf, self.opt.nose_ae_net, 'batch', |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
latent_dim=self.opt.ae_latentno, ae_h=NOSE_H, ae_w=NOSE_W) |
|
self.set_requires_grad(self.netAE, False) |
|
if self.opt.use_local and self.opt.others_ae: |
|
ratio = self.opt.fineSize / 256 |
|
EYE_H = self.opt.EYE_H * ratio |
|
EYE_W = self.opt.EYE_W * ratio |
|
MOUTH_H = self.opt.MOUTH_H * ratio |
|
MOUTH_W = self.opt.MOUTH_W * ratio |
|
self.netAEel = networks.define_G(opt.output_nc, opt.output_nc, opt.ngf, self.opt.nose_ae_net, 'batch', |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
latent_dim=self.opt.ae_latenteye, ae_h=EYE_H, ae_w=EYE_W) |
|
self.netAEer = networks.define_G(opt.output_nc, opt.output_nc, opt.ngf, self.opt.nose_ae_net, 'batch', |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
latent_dim=self.opt.ae_latenteye, ae_h=EYE_H, ae_w=EYE_W) |
|
self.netAEmowhite = networks.define_G(opt.output_nc, opt.output_nc, opt.ngf, self.opt.nose_ae_net, 'batch', |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
latent_dim=self.opt.ae_latentmo, ae_h=MOUTH_H, ae_w=MOUTH_W) |
|
self.netAEmoblack = networks.define_G(opt.output_nc, opt.output_nc, opt.ngf, self.opt.nose_ae_net, 'batch', |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
latent_dim=self.opt.ae_latentmo, ae_h=MOUTH_H, ae_w=MOUTH_W) |
|
self.set_requires_grad(self.netAEel, False) |
|
self.set_requires_grad(self.netAEer, False) |
|
self.set_requires_grad(self.netAEmowhite, False) |
|
self.set_requires_grad(self.netAEmoblack, False) |
|
|
|
|
|
if self.isTrain and self.opt.continuity_loss: |
|
self.nc = 1 |
|
self.netRegressor = networks.define_G(self.nc, 1, opt.ngf, 'regressor', opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids_p, |
|
nnG = opt.regarch) |
|
self.set_requires_grad(self.netRegressor, False) |
|
|
|
if self.isTrain and self.opt.chamfer_loss: |
|
self.nc = 1 |
|
self.netDT1 = networks.define_G(self.nc, self.nc, opt.ngf, opt.netG_dt, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids_p) |
|
self.netDT2 = networks.define_G(self.nc, self.nc, opt.ngf, opt.netG_dt, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids_p) |
|
self.set_requires_grad(self.netDT1, False) |
|
self.set_requires_grad(self.netDT2, False) |
|
self.netLine1 = networks.define_G(self.nc, self.nc, opt.ngf, opt.netG_line, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids_p) |
|
self.netLine2 = networks.define_G(self.nc, self.nc, opt.ngf, opt.netG_line, opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids_p) |
|
self.set_requires_grad(self.netLine1, False) |
|
self.set_requires_grad(self.netLine2, False) |
|
|
|
|
|
if not self.isTrain and self.opt.test_continuity_loss: |
|
self.nc = 1 |
|
self.netRegressor = networks.define_G(self.nc, 1, opt.ngf, 'regressor', opt.norm, |
|
not opt.no_dropout, opt.init_type, opt.init_gain, self.gpu_ids, |
|
nnG = opt.regarch) |
|
self.set_requires_grad(self.netRegressor, False) |
|
|
|
|
|
def set_input(self, input): |
|
AtoB = self.opt.which_direction == 'AtoB' |
|
self.real_A = input['A' if AtoB else 'B'].to(self.device) |
|
self.real_B = input['B' if AtoB else 'A'].to(self.device) |
|
self.image_paths = input['A_paths' if AtoB else 'B_paths'] |
|
self.batch_size = len(self.image_paths) |
|
if self.opt.use_local: |
|
self.real_A_eyel = input['eyel_A'].to(self.device) |
|
self.real_A_eyer = input['eyer_A'].to(self.device) |
|
self.real_A_nose = input['nose_A'].to(self.device) |
|
self.real_A_mouth = input['mouth_A'].to(self.device) |
|
self.real_B_eyel = input['eyel_B'].to(self.device) |
|
self.real_B_eyer = input['eyer_B'].to(self.device) |
|
self.real_B_nose = input['nose_B'].to(self.device) |
|
self.real_B_mouth = input['mouth_B'].to(self.device) |
|
if self.opt.region_enm in [0,1]: |
|
self.center = input['center'] |
|
if self.opt.soft_border: |
|
self.softel = input['soft_eyel_mask'].to(self.device) |
|
self.softer = input['soft_eyer_mask'].to(self.device) |
|
self.softno = input['soft_nose_mask'].to(self.device) |
|
self.softmo = input['soft_mouth_mask'].to(self.device) |
|
if self.opt.compactmask: |
|
self.cmask = input['cmask'].to(self.device) |
|
self.cmask1 = self.cmask*2-1 |
|
self.cmaskel = input['cmaskel'].to(self.device) |
|
self.cmask1el = self.cmaskel*2-1 |
|
self.cmasker = input['cmasker'].to(self.device) |
|
self.cmask1er = self.cmasker*2-1 |
|
self.cmaskmo = input['cmaskmo'].to(self.device) |
|
self.cmask1mo = self.cmaskmo*2-1 |
|
self.real_A_hair = input['hair_A'].to(self.device) |
|
self.real_B_hair = input['hair_B'].to(self.device) |
|
self.mask = input['mask'].to(self.device) |
|
self.mask2 = input['mask2'].to(self.device) |
|
self.real_A_bg = input['bg_A'].to(self.device) |
|
self.real_B_bg = input['bg_B'].to(self.device) |
|
if (self.isTrain and self.opt.chamfer_loss): |
|
self.dt1gt = input['dt1gt'].to(self.device) |
|
self.dt2gt = input['dt2gt'].to(self.device) |
|
if self.isTrain and self.opt.emphasis_conti_face: |
|
self.face_mask = input['face_mask'].cuda(self.gpu_ids_p[0]) |
|
|
|
def getonehot(self,outputs,classes): |
|
[maxv,index] = torch.max(outputs,1) |
|
y = torch.unsqueeze(index,1) |
|
onehot = torch.FloatTensor(self.batch_size,classes).to(self.device) |
|
onehot.zero_() |
|
onehot.scatter_(1,y,1) |
|
return onehot |
|
|
|
def forward(self): |
|
if not self.opt.use_local: |
|
self.fake_B = self.netG(self.real_A) |
|
else: |
|
self.fake_B0 = self.netG(self.real_A) |
|
|
|
outputs1 = self.netCLm(self.real_A_mouth) |
|
onehot1 = self.getonehot(outputs1,2) |
|
|
|
if not self.opt.others_ae: |
|
fake_B_eyel = self.netGLEyel(self.real_A_eyel) |
|
fake_B_eyer = self.netGLEyer(self.real_A_eyer) |
|
fake_B_mouth = self.netGLMouth(self.real_A_mouth) |
|
else: |
|
self.fake_B_eyel1 = self.netGLEyel(self.real_A_eyel) |
|
self.fake_B_eyer1 = self.netGLEyer(self.real_A_eyer) |
|
self.fake_B_mouth1 = self.netGLMouth(self.real_A_mouth) |
|
self.fake_B_eyel2,_ = self.netAEel(self.fake_B_eyel1) |
|
self.fake_B_eyer2,_ = self.netAEer(self.fake_B_eyer1) |
|
|
|
self.fake_B_mouth2 = torch.FloatTensor(self.batch_size,self.opt.output_nc,self.MOUTH_H,self.MOUTH_W).to(self.device) |
|
for i in range(self.batch_size): |
|
if onehot1[i][0] == 1: |
|
self.fake_B_mouth2[i],_ = self.netAEmowhite(self.fake_B_mouth1[i].unsqueeze(0)) |
|
|
|
elif onehot1[i][1] == 1: |
|
self.fake_B_mouth2[i],_ = self.netAEmoblack(self.fake_B_mouth1[i].unsqueeze(0)) |
|
|
|
fake_B_eyel = self.add_with_mask(self.fake_B_eyel2,self.fake_B_eyel1,self.cmaskel) |
|
fake_B_eyer = self.add_with_mask(self.fake_B_eyer2,self.fake_B_eyer1,self.cmasker) |
|
fake_B_mouth = self.add_with_mask(self.fake_B_mouth2,self.fake_B_mouth1,self.cmaskmo) |
|
|
|
if not self.opt.nose_ae: |
|
fake_B_nose = self.netGLNose(self.real_A_nose) |
|
else: |
|
self.fake_B_nose1 = self.netGLNose(self.real_A_nose) |
|
self.fake_B_nose2,_ = self.netAE(self.fake_B_nose1) |
|
fake_B_nose = self.add_with_mask(self.fake_B_nose2,self.fake_B_nose1,self.cmask) |
|
|
|
|
|
if self.opt.region_enm in [0,1]: |
|
self.fake_B_nose = fake_B_nose |
|
self.fake_B_eyel = fake_B_eyel |
|
self.fake_B_eyer = fake_B_eyer |
|
self.fake_B_mouth = fake_B_mouth |
|
|
|
if self.opt.region_enm == 0 and self.opt.soft_border: |
|
self.fake_B_nose = self.masked(fake_B_nose, self.softno) |
|
self.fake_B_eyel = self.masked(fake_B_eyel, self.softel) |
|
self.fake_B_eyer = self.masked(fake_B_eyer, self.softer) |
|
self.fake_B_mouth = self.masked(fake_B_mouth, self.softmo) |
|
elif self.opt.region_enm in [2]: |
|
self.fake_B_nose = self.masked(fake_B_nose,self.cmask) |
|
self.fake_B_eyel = self.masked(fake_B_eyel,self.cmaskel) |
|
self.fake_B_eyer = self.masked(fake_B_eyer,self.cmasker) |
|
self.fake_B_mouth = self.masked(fake_B_mouth,self.cmaskmo) |
|
|
|
|
|
outputs2 = self.netCLh(self.real_A_hair) |
|
onehot2 = self.getonehot(outputs2,3) |
|
|
|
if not self.isTrain: |
|
opt = self.opt |
|
if opt.imagefolder == 'images': |
|
file_name = os.path.join(opt.results_dir, opt.name, '%s_%s' % (opt.phase, opt.which_epoch), 'styleonehot.txt') |
|
else: |
|
file_name = os.path.join(opt.results_dir, opt.name, '%s_%s' % (opt.phase, opt.which_epoch), opt.imagefolder, 'styleonehot.txt') |
|
message = '%s [%d %d] [%d %d %d]' % (self.image_paths[0], onehot1[0][0], onehot1[0][1], |
|
onehot2[0][0], onehot2[0][1], onehot2[0][2]) |
|
with open(file_name, 'a+') as s_file: |
|
s_file.write(message) |
|
s_file.write('\n') |
|
|
|
fake_B_hair = self.netGLHair(self.real_A_hair,onehot2) |
|
fake_B_bg = self.netGLBG(self.real_A_bg) |
|
self.fake_B_hair = self.masked(fake_B_hair,self.mask*self.mask2) |
|
self.fake_B_bg = self.masked(fake_B_bg,self.inverse_mask(self.mask2)) |
|
if not self.opt.compactmask: |
|
self.fake_B1 = self.partCombiner2_bg(fake_B_eyel,fake_B_eyer,fake_B_nose,fake_B_mouth,fake_B_hair,fake_B_bg,self.mask*self.mask2,self.inverse_mask(self.mask2),self.opt.comb_op) |
|
else: |
|
self.fake_B1 = self.partCombiner2_bg(fake_B_eyel,fake_B_eyer,fake_B_nose,fake_B_mouth,fake_B_hair,fake_B_bg,self.mask*self.mask2,self.inverse_mask(self.mask2),self.opt.comb_op,self.opt.region_enm,self.cmaskel,self.cmasker,self.cmask,self.cmaskmo) |
|
|
|
self.fake_B = self.netGCombine(torch.cat([self.fake_B0,self.fake_B1],1)) |
|
|
|
|
|
if self.opt.region_enm in [0,1]: |
|
if self.opt.nose_ae: |
|
self.fake_B_nose_v = padpart(self.fake_B_nose, 'nose', self.center, self.opt, self.device) |
|
self.fake_B_nose_v1 = padpart(self.fake_B_nose1, 'nose', self.center, self.opt, self.device) |
|
self.fake_B_nose_v2 = padpart(self.fake_B_nose2, 'nose', self.center, self.opt, self.device) |
|
self.cmask1no = padpart(self.cmask1, 'nose', self.center, self.opt, self.device) |
|
if self.opt.others_ae: |
|
self.fake_B_eyel_v = padpart(self.fake_B_eyel, 'eyel', self.center, self.opt, self.device) |
|
self.fake_B_eyel_v1 = padpart(self.fake_B_eyel1, 'eyel', self.center, self.opt, self.device) |
|
self.fake_B_eyel_v2 = padpart(self.fake_B_eyel2, 'eyel', self.center, self.opt, self.device) |
|
self.cmask1el = padpart(self.cmask1el, 'eyel', self.center, self.opt, self.device) |
|
self.fake_B_eyer_v = padpart(self.fake_B_eyer, 'eyer', self.center, self.opt, self.device) |
|
self.fake_B_eyer_v1 = padpart(self.fake_B_eyer1, 'eyer', self.center, self.opt, self.device) |
|
self.fake_B_eyer_v2 = padpart(self.fake_B_eyer2, 'eyer', self.center, self.opt, self.device) |
|
self.cmask1er = padpart(self.cmask1er, 'eyer', self.center, self.opt, self.device) |
|
self.fake_B_mouth_v = padpart(self.fake_B_mouth, 'mouth', self.center, self.opt, self.device) |
|
self.fake_B_mouth_v1 = padpart(self.fake_B_mouth1, 'mouth', self.center, self.opt, self.device) |
|
self.fake_B_mouth_v2 = padpart(self.fake_B_mouth2, 'mouth', self.center, self.opt, self.device) |
|
self.cmask1mo = padpart(self.cmask1mo, 'mouth', self.center, self.opt, self.device) |
|
|
|
if not self.isTrain and self.opt.test_continuity_loss: |
|
self.ContinuityForTest(real=1) |
|
|
|
|
|
def backward_D(self): |
|
|
|
|
|
fake_AB = self.fake_AB_pool.query(torch.cat((self.real_A, self.fake_B), 1)) |
|
|
|
pred_fake = self.netD(fake_AB.detach()) |
|
self.loss_D_fake = self.criterionGAN(pred_fake, False) |
|
if self.opt.discriminator_local: |
|
fake_AB_parts = self.getLocalParts(fake_AB) |
|
local_names = ['DLEyel','DLEyer','DLNose','DLMouth','DLHair','DLBG'] |
|
self.loss_D_fake_local = 0 |
|
for i in range(len(fake_AB_parts)): |
|
net = getattr(self, 'net' + local_names[i]) |
|
pred_fake_tmp = net(fake_AB_parts[i].detach()) |
|
addw = self.getaddw(local_names[i]) |
|
self.loss_D_fake_local = self.loss_D_fake_local + self.criterionGAN(pred_fake_tmp, False) * addw |
|
self.loss_D_fake = self.loss_D_fake + self.loss_D_fake_local |
|
|
|
|
|
real_AB = torch.cat((self.real_A, self.real_B), 1) |
|
pred_real = self.netD(real_AB) |
|
self.loss_D_real = self.criterionGAN(pred_real, True) |
|
if self.opt.discriminator_local: |
|
real_AB_parts = self.getLocalParts(real_AB) |
|
local_names = ['DLEyel','DLEyer','DLNose','DLMouth','DLHair','DLBG'] |
|
self.loss_D_real_local = 0 |
|
for i in range(len(real_AB_parts)): |
|
net = getattr(self, 'net' + local_names[i]) |
|
pred_real_tmp = net(real_AB_parts[i]) |
|
addw = self.getaddw(local_names[i]) |
|
self.loss_D_real_local = self.loss_D_real_local + self.criterionGAN(pred_real_tmp, True) * addw |
|
self.loss_D_real = self.loss_D_real + self.loss_D_real_local |
|
|
|
|
|
self.loss_D = (self.loss_D_fake + self.loss_D_real) * 0.5 |
|
|
|
self.loss_D.backward() |
|
|
|
def backward_G(self): |
|
|
|
fake_AB = torch.cat((self.real_A, self.fake_B), 1) |
|
pred_fake = self.netD(fake_AB) |
|
self.loss_G_GAN = self.criterionGAN(pred_fake, True) |
|
if self.opt.discriminator_local: |
|
fake_AB_parts = self.getLocalParts(fake_AB) |
|
local_names = ['DLEyel','DLEyer','DLNose','DLMouth','DLHair','DLBG'] |
|
self.loss_G_GAN_local = 0 |
|
for i in range(len(fake_AB_parts)): |
|
net = getattr(self, 'net' + local_names[i]) |
|
pred_fake_tmp = net(fake_AB_parts[i]) |
|
addw = self.getaddw(local_names[i]) |
|
self.loss_G_GAN_local = self.loss_G_GAN_local + self.criterionGAN(pred_fake_tmp, True) * addw |
|
if self.opt.gan_loss_strategy == 1: |
|
self.loss_G_GAN = (self.loss_G_GAN + self.loss_G_GAN_local) / (len(fake_AB_parts) + 1) |
|
elif self.opt.gan_loss_strategy == 2: |
|
self.loss_G_GAN_local = self.loss_G_GAN_local * 0.25 |
|
self.loss_G_GAN = self.loss_G_GAN + self.loss_G_GAN_local |
|
|
|
|
|
if not self.opt.no_l1_loss: |
|
self.loss_G_L1 = self.criterionL1(self.fake_B, self.real_B) * self.opt.lambda_L1 |
|
|
|
if self.opt.use_local and not self.opt.no_G_local_loss: |
|
local_names = ['eyel','eyer','nose','mouth'] |
|
self.loss_G_local = 0 |
|
for i in range(len(local_names)): |
|
fakeblocal = getattr(self, 'fake_B_' + local_names[i]) |
|
realblocal = getattr(self, 'real_B_' + local_names[i]) |
|
addw = self.getaddw(local_names[i]) |
|
self.loss_G_local = self.loss_G_local + self.criterionL1(fakeblocal,realblocal) * self.opt.lambda_local * addw |
|
self.loss_G_hair_local = self.criterionL1(self.fake_B_hair, self.real_B_hair) * self.opt.lambda_local * self.opt.addw_hair |
|
self.loss_G_bg_local = self.criterionL1(self.fake_B_bg, self.real_B_bg) * self.opt.lambda_local * self.opt.addw_bg |
|
|
|
|
|
if self.opt.chamfer_loss: |
|
if self.fake_B.shape[1] == 3: |
|
tmp = self.fake_B[:,0,...]*0.299+self.fake_B[:,1,...]*0.587+self.fake_B[:,2,...]*0.114 |
|
fake_B_gray = tmp.unsqueeze(1) |
|
else: |
|
fake_B_gray = self.fake_B |
|
if self.real_B.shape[1] == 3: |
|
tmp = self.real_B[:,0,...]*0.299+self.real_B[:,1,...]*0.587+self.real_B[:,2,...]*0.114 |
|
real_B_gray = tmp.unsqueeze(1) |
|
else: |
|
real_B_gray = self.real_B |
|
|
|
gpu_p = self.opt.gpu_ids_p[0] |
|
gpu = self.opt.gpu_ids[0] |
|
if gpu_p != gpu: |
|
fake_B_gray = fake_B_gray.cuda(gpu_p) |
|
real_B_gray = real_B_gray.cuda(gpu_p) |
|
|
|
|
|
self.dt1 = self.netDT1(fake_B_gray) |
|
self.dt2 = self.netDT2(fake_B_gray) |
|
dt1 = self.dt1/2.0+0.5 |
|
dt2 = self.dt2/2.0+0.5 |
|
if self.opt.dt_nonlinear != '': |
|
dt_xmax = torch.Tensor([self.opt.dt_xmax]).cuda(gpu_p) |
|
dt1 = nonlinearDt(dt1, self.opt.dt_nonlinear, dt_xmax) |
|
dt2 = nonlinearDt(dt2, self.opt.dt_nonlinear, dt_xmax) |
|
|
|
|
|
bs = real_B_gray.shape[0] |
|
real_B_gray_line1 = self.netLine1(real_B_gray) |
|
real_B_gray_line2 = self.netLine2(real_B_gray) |
|
self.loss_G_chamfer = (dt1[(real_B_gray<0)&(real_B_gray_line1<0)].sum() + dt2[(real_B_gray>=0)&(real_B_gray_line2>=0)].sum()) / bs * self.opt.lambda_chamfer |
|
if gpu_p != gpu: |
|
self.loss_G_chamfer = self.loss_G_chamfer.cuda(gpu) |
|
|
|
|
|
if gpu_p != gpu: |
|
dt1gt = self.dt1gt.cuda(gpu_p) |
|
dt2gt = self.dt2gt.cuda(gpu_p) |
|
else: |
|
dt1gt = self.dt1gt |
|
dt2gt = self.dt2gt |
|
if self.opt.dt_nonlinear != '': |
|
dt1gt = nonlinearDt(dt1gt, self.opt.dt_nonlinear, dt_xmax) |
|
dt2gt = nonlinearDt(dt2gt, self.opt.dt_nonlinear, dt_xmax) |
|
|
|
self.dt1gt = (self.dt1gt-0.5)*2 |
|
self.dt2gt = (self.dt2gt-0.5)*2 |
|
|
|
fake_B_gray_line1 = self.netLine1(fake_B_gray) |
|
fake_B_gray_line2 = self.netLine2(fake_B_gray) |
|
self.loss_G_chamfer2 = (dt1gt[(fake_B_gray<0)&(fake_B_gray_line1<0)].sum() + dt2gt[(fake_B_gray>=0)&(fake_B_gray_line2>=0)].sum()) / bs * self.opt.lambda_chamfer2 |
|
if gpu_p != gpu: |
|
self.loss_G_chamfer2 = self.loss_G_chamfer2.cuda(gpu) |
|
|
|
|
|
if self.opt.continuity_loss: |
|
|
|
self.get_patches() |
|
self.outputs = self.netRegressor(self.fake_B_patches) |
|
if not self.opt.emphasis_conti_face: |
|
self.loss_G_continuity = (1.0-torch.mean(self.outputs)).cuda(gpu) * self.opt.lambda_continuity |
|
else: |
|
self.loss_G_continuity = torch.mean((1.0-self.outputs)*self.conti_weights).cuda(gpu) * self.opt.lambda_continuity |
|
|
|
|
|
|
|
self.loss_G = self.loss_G_GAN |
|
if 'G_L1' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_L1 |
|
if 'G_local' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_local |
|
if 'G_hair_local' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_hair_local |
|
if 'G_bg_local' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_bg_local |
|
if 'G_chamfer' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_chamfer |
|
if 'G_chamfer2' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_chamfer2 |
|
if 'G_continuity' in self.loss_names: |
|
self.loss_G = self.loss_G + self.loss_G_continuity |
|
|
|
self.loss_G.backward() |
|
|
|
def optimize_parameters(self): |
|
self.forward() |
|
|
|
self.set_requires_grad(self.netD, True) |
|
|
|
if self.opt.discriminator_local: |
|
self.set_requires_grad(self.netDLEyel, True) |
|
self.set_requires_grad(self.netDLEyer, True) |
|
self.set_requires_grad(self.netDLNose, True) |
|
self.set_requires_grad(self.netDLMouth, True) |
|
self.set_requires_grad(self.netDLHair, True) |
|
self.set_requires_grad(self.netDLBG, True) |
|
self.optimizer_D.zero_grad() |
|
self.backward_D() |
|
self.optimizer_D.step() |
|
|
|
|
|
self.set_requires_grad(self.netD, False) |
|
if self.opt.discriminator_local: |
|
self.set_requires_grad(self.netDLEyel, False) |
|
self.set_requires_grad(self.netDLEyer, False) |
|
self.set_requires_grad(self.netDLNose, False) |
|
self.set_requires_grad(self.netDLMouth, False) |
|
self.set_requires_grad(self.netDLHair, False) |
|
self.set_requires_grad(self.netDLBG, False) |
|
self.optimizer_G.zero_grad() |
|
self.backward_G() |
|
self.optimizer_G.step() |
|
|
|
def get_patches(self): |
|
gpu_p = self.opt.gpu_ids_p[0] |
|
gpu = self.opt.gpu_ids[0] |
|
if gpu_p != gpu: |
|
self.fake_B = self.fake_B.cuda(gpu_p) |
|
|
|
patches = [] |
|
if self.isTrain and self.opt.emphasis_conti_face: |
|
weights = [] |
|
W2 = int(W/2) |
|
t = np.random.randint(res,size=2) |
|
for i in range(aa): |
|
for j in range(aa): |
|
p = self.fake_B[:,:,t[0]+i*W:t[0]+(i+1)*W,t[1]+j*W:t[1]+(j+1)*W] |
|
whitenum = torch.sum(p>=0.0) |
|
|
|
if whitenum < 1 or whitenum > W*W-1: |
|
continue |
|
patches.append(p) |
|
if self.isTrain and self.opt.emphasis_conti_face: |
|
weights.append(self.face_mask[:,:,t[0]+i*W+W2,t[1]+j*W+W2]) |
|
self.fake_B_patches = torch.cat(patches, dim=0) |
|
if self.isTrain and self.opt.emphasis_conti_face: |
|
self.conti_weights = torch.cat(weights, dim=0)+1 |
|
|
|
def get_patches_real(self): |
|
|
|
patches = [] |
|
t = np.random.randint(res,size=2) |
|
for i in range(aa): |
|
for j in range(aa): |
|
p = self.real_B[:,:,t[0]+i*W:t[0]+(i+1)*W,t[1]+j*W:t[1]+(j+1)*W] |
|
whitenum = torch.sum(p>=0.0) |
|
|
|
if whitenum < 1 or whitenum > W*W-1: |
|
continue |
|
patches.append(p) |
|
self.real_B_patches = torch.cat(patches, dim=0) |