def main(args): pydiffvg.set_device(th.device('cuda:1')) # Load SVG svg_path = os.path.join(args.svg_path) save_svg_path = svg_path.replace('.svg', '_resave.svg') canvas_width, canvas_height, shapes, shape_groups = pydiffvg.svg_to_scene( svg_path) print("canvas_width", canvas_width) print("canvas_height", canvas_height) print("shapes", shapes) for shape in shapes: print("num_control_points", shape.num_control_points.size(), shape.num_control_points) print("points", shape.points.size(), shape.points) print("is_closed", shape.is_closed) print("stroke_width", shape.stroke_width.size(), shape.stroke_width) print("id", shape.id) print("use_distance_approx", shape.use_distance_approx) print("shape_groups", shape_groups) pydiffvg.save_svg_paths_only(save_svg_path, canvas_width, canvas_height, shapes, shape_groups) # Save initial state ref = render(canvas_width, canvas_height, shapes, shape_groups)
def main(args): pydiffvg.set_device(th.device('cuda:1')) # Load SVG svg = os.path.join(args.svg) canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(svg) # Save initial state ref = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(ref.cpu(), args.out, gamma=2.2)
def main(svg_dirs): pydiffvg.set_device(th.device('cuda:1')) assert os.path.exists(svg_dirs) svg_files = os.listdir(svg_dirs) for svg_file in svg_files: if '.svg' not in svg_file: continue svg_file_path = os.path.join(svg_dirs, svg_file) out_file_path = svg_file_path.replace('.svg', '.png') # Load SVG canvas_width, canvas_height, shapes, shape_groups = pydiffvg.svg_to_scene(svg_file_path) # Save initial state ref = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(ref.cpu(), out_file_path, gamma=2.2)
def gen_func(self): canvas_width, canvas_height, shapes, shape_groups = pydiffvg.svg_to_scene(self.input_path) new_shapes = list() new_groups = list() for dx in range(0, self.multiplier_x): for dy in range(0, self.multiplier_y): for i in range(len(shapes)): new_shape = build_translated_path(shapes[i], dy * canvas_height, dx * canvas_width) new_shapes.append(new_shape) path_group = pydiffvg.ShapeGroup(shape_ids=torch.tensor([len(new_shapes) - 1]), fill_color=None, stroke_color=torch.tensor(self.stroke_color)) new_groups.append(path_group) def gen(): return new_shapes, new_groups return gen
def main(target_path, svg_path, output_dir, num_iter=1000, use_lpips_loss=False): perception_loss = ttools.modules.LPIPS().to(pydiffvg.get_device()) target = torch.from_numpy(skimage.io.imread(target_path, as_gray=False, pilmode="RGB")).to(torch.float32) / 255.0 print("target", target.size()) target = target.pow(gamma) target = target.to(pydiffvg.get_device()) target = target.unsqueeze(0) target = target.permute(0, 3, 1, 2) # NHWC -> NCHW canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(svg_path) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render(canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # The output image is in linear RGB space. Do Gamma correction before saving the image. pydiffvg.imwrite(img.cpu(), f'{output_dir}/init.png', gamma=gamma) points_vars = [] for path in shapes: path.points.requires_grad = True points_vars.append(path.points) color_vars = {} for group in shape_groups: group.fill_color.requires_grad = True color_vars[group.fill_color.data_ptr()] = group.fill_color # color_vars = list(color_vars.values()) # Optimize points_optim = torch.optim.Adam(points_vars, lr=0.1) # color_optim = torch.optim.Adam(color_vars, lr=0.01) # Adam iterations. for t in range(num_iter): print('iteration:', t) points_optim.zero_grad() # color_optim.zero_grad() # Forward pass: render the image. scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups) img = render(canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # Compose img with white background img = img[:, :, 3:4] * img[:, :, :3] + torch.ones(img.shape[0], img.shape[1], 3, device=pydiffvg.get_device()) * (1 - img[:, :, 3:4]) # Save the intermediate render. pydiffvg.imwrite(img.cpu(), f'{output_dir}/iter_{t}.png', gamma=gamma) img = img[:, :, :3] # Convert img from HWC to NCHW img = img.unsqueeze(0) img = img.permute(0, 3, 1, 2) # NHWC -> NCHW # print(img.size()) # print(target.size()) if use_lpips_loss: loss = perception_loss(img, target) else: loss = (img - target).pow(2).mean() print('render loss:', loss.item()) # Backpropagate the gradients. loss.backward() # Take a gradient descent step. points_optim.step() # color_optim.step() for group in shape_groups: group.fill_color.data.clamp_(0.0, 1.0) if t % 10 == 0 or t == num_iter - 1: pydiffvg.save_svg_paths_only(f'{output_dir}/iter_{t}.svg', canvas_width, canvas_height, shapes, shape_groups) # Render the final result. scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups) img = render(canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # Save the intermediate render. pydiffvg.imwrite(img.cpu(), f'{output_dir}/final.png', gamma=gamma) # Convert the intermediate renderings to a video. from subprocess import call call(["ffmpeg", "-framerate", "24", "-i", f"{output_dir}/iter_%d.png", "-vb", "20M", f"{output_dir}/out.mp4"])
def main(args): pydiffvg.set_use_gpu(torch.cuda.is_available()) canvas_width, canvas_height, shapes, shape_groups = pydiffvg.svg_to_scene( args.content_file) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, *scene_args) # Transform to gamma space pydiffvg.imwrite(img.cpu(), 'results/style_transfer/init.png', gamma=1.0) # HWC -> NCHW img = img.unsqueeze(0) img = img.permute(0, 3, 1, 2) # NHWC -> NCHW loader = transforms.Compose([transforms.ToTensor() ]) # transform it into a torch tensor def image_loader(image_name): image = Image.open(image_name) # fake batch dimension required to fit network's input dimensions image = loader(image).unsqueeze(0) return image.to(pydiffvg.get_device(), torch.float) style_img = image_loader(args.style_img) # alpha blend content with a gray background content_img = img[:, :3, :, :] * img[:, 3, :, :] + \ 0.5 * torch.ones([1, 3, img.shape[2], img.shape[3]]) * \ (1 - img[:, 3, :, :]) assert style_img.size() == content_img.size(), \ "we need to import style and content images of the same size" # unloader = transforms.ToPILImage() # reconvert into PIL image 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 device = pydiffvg.get_device() cnn = models.vgg19(pretrained=True).features.to(device).eval() 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) # 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 = mean.clone().view(-1, 1, 1) self.std = std.clone().view(-1, 1, 1) def forward(self, img): # normalize img return (img - self.mean) / self.std # desired depth layers to compute style/content losses : content_layers_default = ['conv_4'] style_layers_default = ['conv_1', 'conv_2', 'conv_3', 'conv_4', 'conv_5'] def get_style_model_and_losses(cnn, normalization_mean, normalization_std, style_img, content_img, content_layers=content_layers_default, style_layers=style_layers_default): cnn = copy.deepcopy(cnn) # 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: 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 def run_style_transfer(cnn, normalization_mean, normalization_std, content_img, style_img, canvas_width, canvas_height, shapes, shape_groups, num_steps=500, style_weight=5000, content_weight=1): """Run the style transfer.""" print('Building the style transfer model..') model, style_losses, content_losses = get_style_model_and_losses( cnn, normalization_mean, normalization_std, style_img, content_img) point_params = [] color_params = [] stroke_width_params = [] for shape in shapes: if isinstance(shape, pydiffvg.Path): point_params.append(shape.points.requires_grad_()) stroke_width_params.append(shape.stroke_width.requires_grad_()) for shape_group in shape_groups: if isinstance(shape_group.fill_color, torch.Tensor): color_params.append(shape_group.fill_color.requires_grad_()) elif isinstance(shape_group.fill_color, pydiffvg.LinearGradient): point_params.append( shape_group.fill_color.begin.requires_grad_()) point_params.append( shape_group.fill_color.end.requires_grad_()) color_params.append( shape_group.fill_color.stop_colors.requires_grad_()) if isinstance(shape_group.stroke_color, torch.Tensor): color_params.append(shape_group.stroke_color.requires_grad_()) elif isinstance(shape_group.stroke_color, pydiffvg.LinearGradient): point_params.append( shape_group.stroke_color.begin.requires_grad_()) point_params.append( shape_group.stroke_color.end.requires_grad_()) color_params.append( shape_group.stroke_color.stop_colors.requires_grad_()) point_optimizer = optim.Adam(point_params, lr=1.0) color_optimizer = optim.Adam(color_params, lr=0.01) stroke_width_optimizers = optim.Adam(stroke_width_params, lr=0.1) print('Optimizing..') run = [0] while run[0] <= num_steps: point_optimizer.zero_grad() color_optimizer.zero_grad() stroke_width_optimizers.zero_grad() scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, *scene_args) # alpha blend img with a gray background img = img[:, :, :3] * img[:, :, 3:4] + \ 0.5 * torch.ones([img.shape[0], img.shape[1], 3]) * \ (1 - img[:, :, 3:4]) pydiffvg.imwrite(img.cpu(), 'results/style_transfer/step_{}.png'.format( run[0]), gamma=1.0) # HWC to NCHW img = img.permute([2, 0, 1]).unsqueeze(0) model(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 style_score *= style_weight content_score *= content_weight loss = style_score + content_score loss.backward() run[0] += 1 if run[0] % 1 == 0: print("run {}:".format(run)) print('Style Loss : {:4f} Content Loss: {:4f}'.format( style_score.item(), content_score.item())) print() point_optimizer.step() color_optimizer.step() stroke_width_optimizers.step() for color in color_params: color.data.clamp_(0, 1) for w in stroke_width_params: w.data.clamp_(0.5, 4.0) return shapes, shape_groups shapes, shape_groups = run_style_transfer(cnn, cnn_normalization_mean, cnn_normalization_std, content_img, style_img, canvas_width, canvas_height, shapes, shape_groups) scene_args = pydiffvg.RenderFunction.serialize_scene(shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, *scene_args) # Transform to gamma space pydiffvg.imwrite(img.cpu(), 'results/style_transfer/output.png', gamma=1.0)
def main(args): canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(args.svg_file) w = int(canvas_width * args.size_scale) h = int(canvas_height * args.size_scale) pfilter = pydiffvg.PixelFilter(type=diffvg.FilterType.box, radius=torch.tensor(0.5)) use_prefiltering = False scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) num_samples_x = 16 num_samples_y = 16 render = pydiffvg.RenderFunction.apply img = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, *scene_args) pydiffvg.imwrite(img.cpu(), 'results/finite_difference_comp/img.png', gamma=1.0) epsilon = 0.1 def perturb_scene(axis, epsilon): shapes[2].points[:, axis] += epsilon # for s in shapes: # if isinstance(s, pydiffvg.Circle): # s.center[axis] += epsilon # elif isinstance(s, pydiffvg.Ellipse): # s.center[axis] += epsilon # elif isinstance(s, pydiffvg.Path): # s.points[:, axis] += epsilon # elif isinstance(s, pydiffvg.Polygon): # s.points[:, axis] += epsilon # elif isinstance(s, pydiffvg.Rect): # s.p_min[axis] += epsilon # s.p_max[axis] += epsilon # for s in shape_groups: # if isinstance(s.fill_color, pydiffvg.LinearGradient): # s.fill_color.begin[axis] += epsilon # s.fill_color.end[axis] += epsilon perturb_scene(0, epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) render = pydiffvg.RenderFunction.apply img0 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, *scene_args) forward_diff = (img0 - img) / (epsilon) forward_diff = forward_diff.sum(axis=2) x_diff_max = 1.5 x_diff_min = -1.5 print(forward_diff.max()) print(forward_diff.min()) forward_diff = cm.viridis( normalize(forward_diff, x_diff_min, x_diff_max).cpu().numpy()) pydiffvg.imwrite( forward_diff, 'results/finite_difference_comp/shared_edge_forward_diff.png', gamma=1.0) perturb_scene(0, -2 * epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) img1 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, *scene_args) backward_diff = (img - img1) / (epsilon) backward_diff = backward_diff.sum(axis=2) print(backward_diff.max()) print(backward_diff.min()) backward_diff = cm.viridis( normalize(backward_diff, x_diff_min, x_diff_max).cpu().numpy()) pydiffvg.imwrite( backward_diff, 'results/finite_difference_comp/shared_edge_backward_diff.png', gamma=1.0) perturb_scene(0, epsilon) num_samples_x = 4 num_samples_y = 4 scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) render_grad = pydiffvg.RenderFunction.render_grad img_grad = render_grad( torch.ones(h, w, 4), w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed *scene_args) print(img_grad[:, :, 0].max()) print(img_grad[:, :, 0].min()) x_diff = cm.viridis( normalize(img_grad[:, :, 0], x_diff_min, x_diff_max).cpu().numpy()) pydiffvg.imwrite(x_diff, 'results/finite_difference_comp/ours_x_diff.png', gamma=1.0)
def main(args): case_name = args.svg_file.split('/')[-1].split('.')[0] canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(args.svg_file) w = int(canvas_width * args.size_scale) h = int(canvas_height * args.size_scale) print(w, h) curve_counts = 0 for s in shapes: if isinstance(s, pydiffvg.Circle): curve_counts += 1 elif isinstance(s, pydiffvg.Ellipse): curve_counts += 1 elif isinstance(s, pydiffvg.Path): curve_counts += len(s.num_control_points) elif isinstance(s, pydiffvg.Polygon): curve_counts += len(s.points) - 1 if s.is_closed: curve_counts += 1 elif isinstance(s, pydiffvg.Rect): curve_counts += 1 print('curve_counts:', curve_counts) pfilter = pydiffvg.PixelFilter(type=diffvg.FilterType.box, radius=torch.tensor(0.5)) use_prefiltering = args.use_prefiltering print('use_prefiltering:', use_prefiltering) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) num_samples_x = args.num_spp num_samples_y = args.num_spp if (use_prefiltering): num_samples_x = 1 num_samples_y = 1 render = pydiffvg.RenderFunction.apply img = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) pydiffvg.imwrite( img.cpu(), f'results/finite_difference_comp/{case_name}_{use_prefiltering}/img.png', gamma=1.0) epsilon = 0.1 def perturb_scene(axis, epsilon): for s in shapes: if isinstance(s, pydiffvg.Circle): s.center[axis] += epsilon elif isinstance(s, pydiffvg.Ellipse): s.center[axis] += epsilon elif isinstance(s, pydiffvg.Path): s.points[:, axis] += epsilon elif isinstance(s, pydiffvg.Polygon): s.points[:, axis] += epsilon elif isinstance(s, pydiffvg.Rect): s.p_min[axis] += epsilon s.p_max[axis] += epsilon for s in shape_groups: if isinstance(s.fill_color, pydiffvg.LinearGradient): s.fill_color.begin[axis] += epsilon s.fill_color.end[axis] += epsilon perturb_scene(0, epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) render = pydiffvg.RenderFunction.apply img0 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) perturb_scene(0, -2 * epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) img1 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) x_diff = (img0 - img1) / (2 * epsilon) x_diff = x_diff.sum(axis=2) x_diff_max = x_diff.max() * args.clamping_factor x_diff_min = x_diff.min() * args.clamping_factor print(x_diff.max()) print(x_diff.min()) x_diff = cm.viridis( normalize(x_diff, x_diff_min, x_diff_max).cpu().numpy()) pydiffvg.imwrite( x_diff, f'results/finite_difference_comp//{case_name}_{use_prefiltering}/finite_x_diff.png', gamma=1.0) perturb_scene(0, epsilon) perturb_scene(1, epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) render = pydiffvg.RenderFunction.apply img0 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) perturb_scene(1, -2 * epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) img1 = render( w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) y_diff = (img0 - img1) / (2 * epsilon) y_diff = y_diff.sum(axis=2) y_diff_max = y_diff.max() * args.clamping_factor y_diff_min = y_diff.min() * args.clamping_factor y_diff = cm.viridis( normalize(y_diff, y_diff_min, y_diff_max).cpu().numpy()) pydiffvg.imwrite( y_diff, f'results/finite_difference_comp/{case_name}_{use_prefiltering}/finite_y_diff.png', gamma=1.0) perturb_scene(1, epsilon) scene_args = pydiffvg.RenderFunction.serialize_scene( canvas_width, canvas_height, shapes, shape_groups, filter=pfilter, use_prefiltering=use_prefiltering) render_grad = pydiffvg.RenderFunction.render_grad img_grad = render_grad( torch.ones(h, w, 4, device=pydiffvg.get_device()), w, # width h, # height num_samples_x, # num_samples_x num_samples_y, # num_samples_y 0, # seed None, # background_image *scene_args) print(img_grad[:, :, 0].max()) print(img_grad[:, :, 0].min()) x_diff = cm.viridis( normalize(img_grad[:, :, 0], x_diff_min, x_diff_max).cpu().numpy()) y_diff = cm.viridis( normalize(img_grad[:, :, 1], y_diff_min, y_diff_max).cpu().numpy()) pydiffvg.imwrite( x_diff, f'results/finite_difference_comp/{case_name}_{use_prefiltering}/ours_x_diff.png', gamma=1.0) pydiffvg.imwrite( y_diff, f'results/finite_difference_comp/{case_name}_{use_prefiltering}/ours_y_diff.png', gamma=1.0)
def main(): pydiffvg.set_device(th.device('cuda:1')) # Load SVG svg = os.path.join("imgs", "peppers.svg") canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(svg) # Save initial state ref = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(ref.cpu(), 'results/gaussian_blur/init.png', gamma=2.2) target = F.gaussian_filter(ref.cpu().numpy(), [10, 10, 0]) target = th.from_numpy(target).to(ref.device) pydiffvg.imwrite(target.cpu(), 'results/gaussian_blur/target.png', gamma=2.2) # Collect variables to optimize points_vars = [] width_vars = [] for path in shapes: path.points.requires_grad = True points_vars.append(path.points) path.stroke_width.requires_grad = True width_vars.append(path.stroke_width) color_vars = [] for group in shape_groups: # do not optimize alpha group.fill_color[..., :3].requires_grad = True color_vars.append(group.fill_color) # Optimize points_optim = th.optim.Adam(points_vars, lr=1.0) width_optim = th.optim.Adam(width_vars, lr=1.0) color_optim = th.optim.Adam(color_vars, lr=0.01) for t in range(20): print('\niteration:', t) points_optim.zero_grad() width_optim.zero_grad() color_optim.zero_grad() # Forward pass: render the image. img = render(canvas_width, canvas_height, shapes, shape_groups) # Save the intermediate render. pydiffvg.imwrite(img.cpu(), 'results/gaussian_blur/iter_{}.png'.format(t), gamma=2.2) loss = (img - target)[..., :3].pow(2).mean() print('alpha:', img[..., 3].mean().item()) print('render loss:', loss.item()) # Backpropagate the gradients. loss.backward() # Take a gradient descent step. points_optim.step() width_optim.step() color_optim.step() for group in shape_groups: group.fill_color.data.clamp_(0.0, 1.0) # Final render img = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(img.cpu(), 'results/gaussian_blur/final.png', gamma=2.2) # Convert the intermediate renderings to a video. from subprocess import call call([ "ffmpeg", "-framerate", "24", "-i", "results/gaussian_blur/iter_%d.png", "-vb", "20M", "results/gaussian_blur/out.mp4" ])
inmat[0:2,:]=(np.random.rand(2,3)-0.5)*2 decomp=OptimizableSvg.TransformTools.decompose(inmat) outmat=OptimizableSvg.TransformTools.recompose(torch.tensor(decomp[0],dtype=torch.float32),torch.tensor(decomp[1],dtype=torch.float32),torch.tensor(decomp[2],dtype=torch.float32),torch.tensor(decomp[3],dtype=torch.float32)).numpy() dif=np.linalg.norm(inmat-outmat) if dif > 1e-3: print(dif) print(inmat) print(outmat) print(decomp)""" #infile='../../data/test_data/linear_grad_alpha_aspaths.svg' #infile='../../data/note_small.svg' infile = 'linux.svg' canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(infile) scene_args = pydiffvg.RenderFunction.serialize_scene(\ canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed *scene_args) # The output image is in linear RGB space. Do Gamma correction before saving the image. pydiffvg.imwrite(img.cpu(), 'test_old.png', gamma=1.0) #optim=OptimizableSvg('linux.svg',verbose=True) optim = OptimizableSvg(infile, verbose=True)
def main(): parser = argparse.ArgumentParser() parser.add_argument("--svg", default=os.path.join("imgs", "seamcarving", "hokusai.svg")) parser.add_argument("--optim_steps", default=10, type=int) parser.add_argument("--lr", default=1e-1, type=int) args = parser.parse_args() name = os.path.splitext(os.path.basename(args.svg))[0] root = os.path.join("results", "seam_carving", name) svg_root = os.path.join(root, "svg") os.makedirs(root, exist_ok=True) os.makedirs(os.path.join(root, "svg"), exist_ok=True) pydiffvg.set_use_gpu(False) # pydiffvg.set_device(th.device('cuda')) # Load SVG print("loading svg %s" % args.svg) canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(args.svg) print("done loading") max_size = 512 scale_factor = max_size / max(canvas_width, canvas_height) print("rescaling from %dx%d with scale %f" % (canvas_width, canvas_height, scale_factor)) canvas_width = int(canvas_width * scale_factor) canvas_height = int(canvas_height * scale_factor) print("new shape %dx%d" % (canvas_width, canvas_height)) vector_rescale(shapes, scale_x=scale_factor, scale_y=scale_factor) # Shrink image by 33 % # num_seams_to_remove = 2 num_seams_to_remove = canvas_width // 3 new_canvas_width = canvas_width - num_seams_to_remove scaling = new_canvas_width * 1.0 / canvas_width # Naive scaling baseline print("rendering naive rescaling...") vector_rescale(shapes, scale_x=scaling) resized = render(new_canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(resized.cpu(), os.path.join(root, 'uniform_scaling.png'), gamma=2.2) pydiffvg.save_svg(os.path.join(svg_root, 'uniform_scaling.svg'), canvas_width, canvas_height, shapes, shape_groups, use_gamma=False) vector_rescale(shapes, scale_x=1.0 / scaling) # bring back original coordinates print("saved naiving scaling") # Save initial state print("rendering initial state...") im = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(im.cpu(), os.path.join(root, 'init.png'), gamma=2.2) pydiffvg.save_svg(os.path.join(svg_root, 'init.svg'), canvas_width, canvas_height, shapes, shape_groups, use_gamma=False) print("saved initial state") # Optimize # color_optim = th.optim.Adam(color_vars, lr=0.01) retargeted = im[..., :3].cpu().numpy() previous_width = canvas_width print("carving seams") for seam_idx in range(num_seams_to_remove): print('\nseam', seam_idx + 1, 'of', num_seams_to_remove) # Remove a seam retargeted = carve_seam(retargeted) current_width = canvas_width - seam_idx - 1 scale_factor = current_width * 1.0 / previous_width previous_width = current_width padded = np.zeros((canvas_height, canvas_width, 4)) padded[:, :-seam_idx - 1, :3] = retargeted padded[:, :-seam_idx - 1, -1] = 1.0 # alpha padded = th.from_numpy(padded).to(im.device) # Remap points to the smaller canvas and # collect variables to optimize points_vars = [] # width_vars = [] mini, maxi = canvas_width, 0 for path in shapes: path.points.requires_grad = False x = path.points[..., 0] y = path.points[..., 1] # rescale x = x * scale_factor # clip to canvas path.points[..., 0] = th.clamp(x, 0, current_width) path.points[..., 1] = th.clamp(y, 0, canvas_height) path.points.requires_grad = True points_vars.append(path.points) path.stroke_width.requires_grad = True # width_vars.append(path.stroke_width) mini = min(mini, path.points.min().item()) maxi = max(maxi, path.points.max().item()) print("points", mini, maxi, "scale", scale_factor) # recreate an optimizer so we don't carry over the previous update # (momentum)? geom_optim = th.optim.Adam(points_vars, lr=args.lr) for step in range(args.optim_steps): geom_optim.zero_grad() img = render(canvas_width, canvas_height, shapes, shape_groups, samples=2) pydiffvg.imwrite(img.cpu(), os.path.join( root, "seam_%03d_iter_%02d.png" % (seam_idx, step)), gamma=2.2) # NO alpha loss = (img - padded)[..., :3].pow(2).mean() # loss = (img - padded).pow(2).mean() print('render loss:', loss.item()) # Backpropagate the gradients. loss.backward() # Take a gradient descent step. geom_optim.step() pydiffvg.save_svg(os.path.join(svg_root, "seam%03d.svg" % seam_idx), canvas_width - seam_idx, canvas_height, shapes, shape_groups, use_gamma=False) for path in shapes: mini = min(mini, path.points.min().item()) maxi = max(maxi, path.points.max().item()) print("points", mini, maxi) img = render(canvas_width, canvas_height, shapes, shape_groups) img = img[:, :-num_seams_to_remove] pydiffvg.imwrite(img.cpu(), os.path.join(root, 'final.png'), gamma=2.2) pydiffvg.imwrite(retargeted, os.path.join(root, 'ref.png'), gamma=2.2) pydiffvg.save_svg(os.path.join(svg_root, 'final.svg'), canvas_width - num_seams_to_remove + 1, canvas_height, shapes, shape_groups, use_gamma=False) # Convert the intermediate renderings to a video. from subprocess import call call([ "ffmpeg", "-framerate", "24", "-i", os.path.join(root, "seam_%03d_iter_00.png"), "-vb", "20M", os.path.join(root, "out.mp4") ])
def main(args): # set device -> use cpu now since I haven't solved the nvcc issue pydiffvg.set_use_gpu(False) # pydiffvg.set_device(torch.device('cuda:1')) # use L2 for now # perception_loss = ttools.modules.LPIPS().to(pydiffvg.get_device()) # generate a texture synthesized target_img = texture_syn(args.target) tar_h, tar_w = target_img.shape[1], target_img.shape[0] canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(args.svg_path) # svgpathtools for checking the bounding box # paths, _, _ = svg2paths2(args.svg_path) # print(len(paths)) # xmin, xmax, ymin, ymax = big_bounding_box(paths) # print(xmin, xmax, ymin, ymax) # input("check") print('tar h : %d tar w : %d' % (tar_h, tar_w)) print('canvas h : %d canvas w : %d' % (canvas_height, canvas_width)) scale_ratio = tar_h / canvas_height print("scale ratio : ", scale_ratio) # input("check") for path in shapes: path.points[..., 0] = path.points[..., 0] * scale_ratio path.points[..., 1] = path.points[..., 1] * scale_ratio init_img = render(tar_w, tar_h, shapes, shape_groups) pydiffvg.imwrite(init_img.cpu(), 'results/texture_synthesis/%d/init.png' % (args.case), gamma=2.2) # input("check") random.seed(1234) torch.manual_seed(1234) points_vars = [] for path in shapes: path.points.requires_grad = True points_vars.append(path.points) color_vars = [] for group in shape_groups: group.fill_color.requires_grad = True color_vars.append(group.fill_color) # Optimize points_optim = torch.optim.Adam(points_vars, lr=1.0) color_optim = torch.optim.Adam(color_vars, lr=0.01) target = torch.from_numpy(target_img).to(torch.float32) / 255.0 target = target.pow(2.2) target = target.to(pydiffvg.get_device()) target = target.unsqueeze(0) target = target.permute(0, 3, 1, 2) # NHWC -> NCHW canvas_width, canvas_height = target.shape[3], target.shape[2] # print('canvas h : %d canvas w : %d' % (canvas_height, canvas_width)) # input("check") for t in range(args.max_iter): print('iteration:', t) points_optim.zero_grad() color_optim.zero_grad() cur_img = render(canvas_width, canvas_height, shapes, shape_groups) pydiffvg.imwrite(cur_img.cpu(), 'results/texture_synthesis/%d/iter_%d.png' % (args.case, t), gamma=2.2) cur_img = cur_img[:, :, :3] cur_img = cur_img.unsqueeze(0) cur_img = cur_img.permute(0, 3, 1, 2) # NHWC -> NCHW # perceptual loss # loss = perception_loss(cur_img, target) # l2 loss loss = (cur_img - target).pow(2).mean() print('render loss:', loss.item()) loss.backward() points_optim.step() color_optim.step() for group in shape_groups: group.fill_color.data.clamp_(0.0, 1.0) # write svg if t % 10 == 0 or t == args.max_iter - 1: pydiffvg.save_svg( 'results/texture_synthesis/%d/iter_%d.svg' % (args.case, t), canvas_width, canvas_height, shapes, shape_groups) # render final result final_img = render(tar_h, tar_w, shapes, shape_groups) pydiffvg.imwrite(final_img.cpu(), 'results/texture_synthesis/%d/final.png' % (args.case), gamma=2.2) from subprocess import call call([ "ffmpeg", "-framerate", "24", "-i", "results/texture_synthesis/%d/iter_%d.png" % (args.case), "-vb", "20M", "results/texture_synthesis/%d/out.mp4" % (args.case) ]) # make gif make_gif("results/texture_synthesis/%d" % (args.case), "results/texture_synthesis/%d/out.gif" % (args.case), frame_every_X_steps=1, repeat_ending=3, total_iter=args.max_iter)
def main(args): inceptionv3 = models.inception_v3(pretrained=True, transform_input=False).cuda() inceptionv3.eval() perception_loss = ttools.modules.LPIPS().to(pydiffvg.get_device()) canvas_width, canvas_height, shapes, shape_groups = \ pydiffvg.svg_to_scene(args.svg) scene_args = pydiffvg.RenderFunction.serialize_scene( \ canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # The output image is in linear RGB space. Do Gamma correction before saving the image. pydiffvg.imwrite(img.cpu(), 'logs/refine_svg/init.png', gamma=gamma) pydiffvg.imwrite(img.cpu(), 'logs/refine_svg/init_.png') points_vars = [] for path in shapes: path.points.requires_grad = True points_vars.append(path.points) # color_vars = {} # for group in shape_groups: # group.fill_color.requires_grad = True # color_vars[group.fill_color.data_ptr()] = group.fill_color # color_vars = list(color_vars.values()) # Optimize points_optim = torch.optim.Adam(points_vars, lr=1.0) # color_optim = torch.optim.Adam(color_vars, lr=0.01) # Adam iterations. for t in range(args.num_iter): print('iteration:', t) points_optim.zero_grad() # color_optim.zero_grad() # Forward pass: render the image. scene_args = pydiffvg.RenderFunction.serialize_scene( \ canvas_width, canvas_height, shapes, shape_groups) img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # Compose img with white background img = img[:, :, 3:4] * img[:, :, :3] + torch.ones( img.shape[0], img.shape[1], 3, device=pydiffvg.get_device()) * (1 - img[:, :, 3:4]) # Save the intermediate render. pydiffvg.imwrite(img.cpu(), 'logs/refine_svg/iter_{}.png'.format(t), gamma=gamma) img = img[:, :, :3] # Convert img from HWC to NCHW img = img.unsqueeze(0) img = img.permute(0, 3, 1, 2) # NHWC -> NCHW output = inceptionv3.forward(img.cuda()) get_class(output) target = torch.autograd.Variable(torch.LongTensor([291]), requires_grad=False).cuda() loss = torch.nn.CrossEntropyLoss()(output, target) print('render loss:', loss.item()) # Backpropagate the gradients. loss.backward() # Take a gradient descent step. points_optim.step() # color_optim.step() # for group in shape_groups: # group.fill_color.data.clamp_(0.0, 1.0) if t % 10 == 0 or t == args.num_iter - 1: pydiffvg.save_svg('logs/refine_svg/iter_{}.svg'.format(t), canvas_width, canvas_height, shapes, shape_groups) # Render the final result. scene_args = pydiffvg.RenderFunction.serialize_scene( \ canvas_width, canvas_height, shapes, shape_groups) img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) # Save the intermediate render. pydiffvg.imwrite(img.cpu(), 'logs/refine_svg/final.png'.format(t), gamma=gamma)
import pydiffvg import matplotlib.pyplot as plt canvas_width, canvas_height, shapes, shape_groups = pydiffvg.svg_to_scene( "data/lion.svg") scene_args = pydiffvg.RenderFunction.serialize_scene(canvas_width, canvas_height, shapes, shape_groups) render = pydiffvg.RenderFunction.apply img = render( canvas_width, # width canvas_height, # height 2, # num_samples_x 2, # num_samples_y 0, # seed None, # bg *scene_args) plt.imshow(img.detach().cpu()) plt.show()