Spaces:
Configuration error
Configuration error
| import sys | |
| import numpy | |
| import torch | |
| import torch.nn as nn | |
| from torch.autograd import Function | |
| from torch.optim.lr_scheduler import _LRScheduler | |
| import torchvision | |
| import torchvision.transforms as transforms | |
| import torchvision.utils as vutils | |
| from torch.utils.data import DataLoader | |
| from dataset import Dataset_FullImg, Dataset_DiscRegion | |
| import math | |
| import PIL | |
| import matplotlib.pyplot as plt | |
| import seaborn as sns | |
| import collections | |
| import logging | |
| import math | |
| import os | |
| import time | |
| from datetime import datetime | |
| import dateutil.tz | |
| from typing import Union, Optional, List, Tuple, Text, BinaryIO | |
| import pathlib | |
| import warnings | |
| import numpy as np | |
| from PIL import Image, ImageDraw, ImageFont, ImageColor | |
| from lucent.optvis.param.spatial import pixel_image, fft_image, init_image | |
| from lucent.optvis.param.color import to_valid_rgb | |
| from torchvision.models import vgg19 | |
| import torch.nn.functional as F | |
| import cfg | |
| import warnings | |
| from collections import OrderedDict | |
| import numpy as np | |
| from tqdm import tqdm | |
| from PIL import Image | |
| import torch | |
| args = cfg.parse_args() | |
| device = torch.device('cuda', args.gpu_device) | |
| cnn = vgg19(pretrained=True).features.to(device).eval() | |
| content_layers_default = ['conv_4'] | |
| style_layers_default = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5'] | |
| cnn_normalization_mean = torch.tensor([0.485, 0.456, 0.406]).to(device) | |
| cnn_normalization_std = torch.tensor([0.229, 0.224, 0.225]).to(device) | |
| class ContentLoss(nn.Module): | |
| def __init__(self, target,): | |
| super(ContentLoss, self).__init__() | |
| # we 'detach' the target content from the tree used | |
| # to dynamically compute the gradient: this is a stated value, | |
| # not a variable. Otherwise the forward method of the criterion | |
| # will throw an error. | |
| self.target = target.detach() | |
| def forward(self, input): | |
| self.loss = F.mse_loss(input, self.target) | |
| return input | |
| def gram_matrix(input): | |
| a, b, c, d = input.size() # a=batch size(=1) | |
| # b=number of feature maps | |
| # (c,d)=dimensions of a f. map (N=c*d) | |
| features = input.view(a * b, c * d) # resise F_XL into \hat F_XL | |
| G = torch.mm(features, features.t()) # compute the gram product | |
| # we 'normalize' the values of the gram matrix | |
| # by dividing by the number of element in each feature maps. | |
| return G.div(a * b * c * d) | |
| class StyleLoss(nn.Module): | |
| def __init__(self, target_feature): | |
| super(StyleLoss, self).__init__() | |
| self.target = gram_matrix(target_feature).detach() | |
| def forward(self, input): | |
| G = gram_matrix(input) | |
| self.loss = F.mse_loss(G, self.target) | |
| return input | |
| # create a module to normalize input image so we can easily put it in a | |
| # nn.Sequential | |
| class Normalization(nn.Module): | |
| def __init__(self, mean, std): | |
| super(Normalization, self).__init__() | |
| # .view the mean and std to make them [C x 1 x 1] so that they can | |
| # directly work with image Tensor of shape [B x C x H x W]. | |
| # B is batch size. C is number of channels. H is height and W is width. | |
| self.mean = torch.tensor(mean).view(-1, 1, 1) | |
| self.std = torch.tensor(std).view(-1, 1, 1) | |
| def forward(self, img): | |
| # normalize img | |
| return (img - self.mean) / self.std | |
| def run_precpt(cnn, normalization_mean, normalization_std, | |
| content_img, style_img, input_img, | |
| style_weight=1000000, content_weight=1): | |
| model, style_losses, content_losses = precpt_loss(cnn, | |
| normalization_mean, normalization_std, style_img, content_img) | |
| # We want to optimize the input and not the model parameters so we | |
| # update all the requires_grad fields accordingly | |
| model.requires_grad_(False) | |
| input_img.requires_grad_(True) | |
| model(input_img) | |
| style_score = 0 | |
| content_score = 0 | |
| for sl in style_losses: | |
| style_score += sl.loss | |
| for cl in content_losses: | |
| content_score += cl.loss | |
| content_weight = 100 | |
| style_weight = 100000 | |
| style_score *= style_weight | |
| content_score *= content_weight | |
| loss = style_score + content_score | |
| # loss = content_score | |
| return loss | |
| def precpt_loss(cnn, normalization_mean, normalization_std, | |
| style_img, content_img, | |
| content_layers=content_layers_default, | |
| style_layers=style_layers_default): | |
| # normalization module | |
| normalization = Normalization(normalization_mean, normalization_std).to(device) | |
| # just in order to have an iterable access to or list of content/syle | |
| # losses | |
| content_losses = [] | |
| style_losses = [] | |
| # assuming that cnn is a nn.Sequential, so we make a new nn.Sequential | |
| # to put in modules that are supposed to be activated sequentially | |
| model = nn.Sequential(normalization) | |
| i = 0 # increment every time we see a conv | |
| for layer in cnn.children(): | |
| if isinstance(layer, nn.Conv2d): | |
| i += 1 | |
| name = 'conv_{}'.format(i) | |
| elif isinstance(layer, nn.ReLU): | |
| name = 'relu_{}'.format(i) | |
| # The in-place version doesn't play very nicely with the ContentLoss | |
| # and StyleLoss we insert below. So we replace with out-of-place | |
| # ones here. | |
| layer = nn.ReLU(inplace=False) | |
| elif isinstance(layer, nn.MaxPool2d): | |
| name = 'pool_{}'.format(i) | |
| elif isinstance(layer, nn.BatchNorm2d): | |
| name = 'bn_{}'.format(i) | |
| else: | |
| raise RuntimeError('Unrecognized layer: {}'.format(layer.__class__.__name__)) | |
| model.add_module(name, layer) | |
| if name in content_layers: | |
| # add content loss: | |
| target = model(content_img).detach() | |
| content_loss = ContentLoss(target) | |
| model.add_module("content_loss_{}".format(i), content_loss) | |
| content_losses.append(content_loss) | |
| if name in style_layers: | |
| # add style loss: | |
| if style_img.size(1) == 1: | |
| style_img = style_img.expand(style_img.size(0),3, style_img.size(2),style_img.size(3)) | |
| target_feature = model(style_img).detach() | |
| style_loss = StyleLoss(target_feature) | |
| model.add_module("style_loss_{}".format(i), style_loss) | |
| style_losses.append(style_loss) | |
| # now we trim off the layers after the last content and style losses | |
| for i in range(len(model) - 1, -1, -1): | |
| if isinstance(model[i], ContentLoss) or isinstance(model[i], StyleLoss): | |
| break | |
| model = model[:(i + 1)] | |
| return model, style_losses, content_losses | |