from __future__ import annotations from time import sleep import pydiffvg import torch import random from random import uniform from gmtypes import GradientMesh, Quad, Patch, Point, join_quads def quads(): return [ Quad.random(), Quad.random(), Quad.random(), Quad.random(), ] def rand_quad_test(filename='random_quad.png', width=256, height=256, degree=4, num_control_points=2): pydiffvg.set_use_gpu(torch.cuda.is_available()) render = pydiffvg.RenderFunction.apply patch = Patch.random() shape_groups = [patch.as_shape_group()] shapes = [patch.as_path(width, height)] scene_args = pydiffvg.RenderFunction.serialize_scene(width, height, shapes, shape_groups) img = render(width, height, 2, 2, 0, None, *scene_args) pydiffvg.imwrite(img.cpu(), f"test_data/{filename}", gamma=2.2) return img def mult_quad_test(filename='multiple_quads.png', width=1024, height=1024, num_control_points=None, mask=None, seed=None): random.seed(seed) mask = mask or [1, 1, 1, 1] pydiffvg.set_use_gpu(torch.cuda.is_available()) render = pydiffvg.RenderFunction.apply a, b, c, d = quads() join_quads(a, b, c, d) to_render = [a, b, c, d] to_render = [x for x in to_render if mask[to_render.index(x)]] shape_groups = [patch.as_shape_group(color=( uniform(0, 1), uniform(0, 1), uniform(0, 1), 0.8 )) for patch in to_render] for i in range(len(to_render)): shape_groups[i].shape_ids = torch.tensor([i]) shapes = [patch.as_path(width, height) for patch in to_render] scene_args = pydiffvg.RenderFunction.serialize_scene(width, height, shapes, shape_groups) img = render(width, height, 2, 2, 0, None, *scene_args) pydiffvg.imwrite(img.cpu(), f"test_data/{filename}", gamma=2.2) return img.clone() def om(): filename = 'optimize_test.png' pydiffvg.set_use_gpu(torch.cuda.is_available()) render = pydiffvg.RenderFunction.apply target = mult_quad_test(width=256, height=256) squad = quads() join_quads(*squad) gm = GradientMesh(*squad) points_n = [] for s in squad: out = [] for pt in s.points: out.append([pt.x, pt.y]) for cpt in pt.controls: out.append([cpt.x, cpt.y]) points_n.append(out) points_n = torch.tensor(points_n, requires_grad=True) color = torch.tensor([s.color for s in squad], requires_grad=True) paths = [s.as_path() for s in squad] path_groups = [pydiffvg.ShapeGroup(shape_ids=torch.tensor([i]), fill_color=torch.tensor(squad[i].color)) for i in range(len(squad))] scene_args = pydiffvg.RenderFunction.serialize_scene( 256, 256, paths, path_groups ) img = render(256, # width 256, # height 2, # num_samples_x 2, # num_samples_y 1, # seed None, *scene_args) points, controls, color = [torch.tensor(x, requires_grad=True) for x in gm.to_numbers()] optimizer = torch.optim.Adam([points, color, points_n], lr=1e-2) for t in range(180): print(f"iteration {t}") optimizer.zero_grad() points_n.data = torch.tensor( GradientMesh.from_path_points(points_n, color).to_path_points() ) for i in range(len(paths)): paths[i].points = points_n[i] * 256 for i in range(len(path_groups)): path_groups[i].fill_color = color[i] scene_args = pydiffvg.RenderFunction.serialize_scene( 256, 256, paths, path_groups) img = render(256, # width 256, # height 2, # num_samples_x 2, # num_samples_y t+1, # seed None, *scene_args) pydiffvg.imwrite(img.cpu(), f'test_data/test_curve/iter_{filename}_' f'{str(t).zfill(5)}.png', gamma=2.2) loss = (img - target).pow(2).sum() loss.backward() print(f'loss: {loss}') print(f'points.grad {points.grad}') print(f'color.grad {color.grad}') optimizer.step() def slideshow(n=30, s=1, do_mask=False): mask = None for i in range(n): if do_mask: mask = [1] * 4 print(i % n) mask[i % 4] = 0 print(mask) mult_quad_test(mask=mask) sleep(s) def get_mesh(): a, b, c, d = quads() join_quads(a,b,c,d) gm = GradientMesh(a, b, c, d) return gm