Example #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)
Example #2
0
    def serialize_scene(canvas_width,
                        canvas_height,
                        shapes,
                        shape_groups,
                        filter=pydiffvg.PixelFilter(type=diffvg.FilterType.box,
                                                    radius=torch.tensor(0.5)),
                        output_type=OutputType.color,
                        use_prefiltering=False,
                        eval_positions=torch.tensor([])):
        """
            Given a list of shapes, convert them to a linear list of argument,
            so that we can use it in PyTorch.
        """
        num_shapes = len(shapes)
        num_shape_groups = len(shape_groups)
        args = []
        args.append(canvas_width)
        args.append(canvas_height)
        args.append(num_shapes)
        args.append(num_shape_groups)
        args.append(output_type)
        args.append(use_prefiltering)
        args.append(eval_positions.to(pydiffvg.get_device()))
        for shape in shapes:
            use_thickness = False
            if isinstance(shape, pydiffvg.Circle):
                assert(shape.center.is_contiguous())
                args.append(diffvg.ShapeType.circle)
                args.append(shape.radius.cpu())
                args.append(shape.center.cpu())
            elif isinstance(shape, pydiffvg.Ellipse):
                assert(shape.radius.is_contiguous())
                assert(shape.center.is_contiguous())
                args.append(diffvg.ShapeType.ellipse)
                args.append(shape.radius.cpu())
                args.append(shape.center.cpu())
            elif isinstance(shape, pydiffvg.Path):
                assert(shape.num_control_points.is_contiguous())
                assert(shape.points.is_contiguous())
                assert(shape.points.shape[1] == 2)
                assert(torch.isfinite(shape.points).all())
                args.append(diffvg.ShapeType.path)
                args.append(shape.num_control_points.to(torch.int32).cpu())
                args.append(shape.points.cpu())
                if len(shape.stroke_width.shape) > 0 and shape.stroke_width.shape[0] > 1:
                    assert(torch.isfinite(shape.stroke_width).all())
                    use_thickness = True
                    args.append(shape.stroke_width.cpu())
                else:
                    args.append(None)
                args.append(shape.is_closed)
                args.append(shape.use_distance_approx)
            elif isinstance(shape, pydiffvg.Polygon):
                assert(shape.points.is_contiguous())
                assert(shape.points.shape[1] == 2)
                args.append(diffvg.ShapeType.path)
                if shape.is_closed:
                    args.append(torch.zeros(shape.points.shape[0], dtype=torch.int32))
                else:
                    args.append(torch.zeros(shape.points.shape[0] - 1, dtype=torch.int32))
                args.append(shape.points.cpu())
                args.append(None)
                args.append(shape.is_closed)
                args.append(False)  # use_distance_approx
            elif isinstance(shape, pydiffvg.Rect):
                assert(shape.p_min.is_contiguous())
                assert(shape.p_max.is_contiguous())
                args.append(diffvg.ShapeType.rect)
                args.append(shape.p_min.cpu())
                args.append(shape.p_max.cpu())
            else:
                assert(False)
            if use_thickness:
                args.append(torch.tensor(0.0))
            else:
                args.append(shape.stroke_width.cpu())

        for shape_group in shape_groups:
            assert(shape_group.shape_ids.is_contiguous())
            args.append(shape_group.shape_ids.to(torch.int32).cpu())
            # Fill color
            if shape_group.fill_color is None:
                args.append(None)
            elif isinstance(shape_group.fill_color, torch.Tensor):
                assert(shape_group.fill_color.is_contiguous())
                args.append(diffvg.ColorType.constant)
                args.append(shape_group.fill_color.cpu())
            elif isinstance(shape_group.fill_color, pydiffvg.LinearGradient):
                assert(shape_group.fill_color.begin.is_contiguous())
                assert(shape_group.fill_color.end.is_contiguous())
                assert(shape_group.fill_color.offsets.is_contiguous())
                assert(shape_group.fill_color.stop_colors.is_contiguous())
                args.append(diffvg.ColorType.linear_gradient)
                args.append(shape_group.fill_color.begin.cpu())
                args.append(shape_group.fill_color.end.cpu())
                args.append(shape_group.fill_color.offsets.cpu())
                args.append(shape_group.fill_color.stop_colors.cpu())
            elif isinstance(shape_group.fill_color, pydiffvg.RadialGradient):
                assert(shape_group.fill_color.center.is_contiguous())
                assert(shape_group.fill_color.radius.is_contiguous())
                assert(shape_group.fill_color.offsets.is_contiguous())
                assert(shape_group.fill_color.stop_colors.is_contiguous())
                args.append(diffvg.ColorType.radial_gradient)
                args.append(shape_group.fill_color.center.cpu())
                args.append(shape_group.fill_color.radius.cpu())
                args.append(shape_group.fill_color.offsets.cpu())
                args.append(shape_group.fill_color.stop_colors.cpu())

            if shape_group.fill_color is not None:
                # go through the underlying shapes and check if they are all closed
                for shape_id in shape_group.shape_ids:
                    if isinstance(shapes[shape_id], pydiffvg.Path):
                        if not shapes[shape_id].is_closed:
                            warnings.warn("Detected non-closed paths with fill color. This might causes unexpected results.", Warning)

            # Stroke color
            if shape_group.stroke_color is None:
                args.append(None)
            elif isinstance(shape_group.stroke_color, torch.Tensor):
                assert(shape_group.stroke_color.is_contiguous())
                args.append(diffvg.ColorType.constant)
                args.append(shape_group.stroke_color.cpu())
            elif isinstance(shape_group.stroke_color, pydiffvg.LinearGradient):
                assert(shape_group.stroke_color.begin.is_contiguous())
                assert(shape_group.stroke_color.end.is_contiguous())
                assert(shape_group.stroke_color.offsets.is_contiguous())
                assert(shape_group.stroke_color.stop_colors.is_contiguous())
                assert(torch.isfinite(shape_group.stroke_color.stop_colors).all())
                args.append(diffvg.ColorType.linear_gradient)
                args.append(shape_group.stroke_color.begin.cpu())
                args.append(shape_group.stroke_color.end.cpu())
                args.append(shape_group.stroke_color.offsets.cpu())
                args.append(shape_group.stroke_color.stop_colors.cpu())
            elif isinstance(shape_group.stroke_color, pydiffvg.RadialGradient):
                assert(shape_group.stroke_color.center.is_contiguous())
                assert(shape_group.stroke_color.radius.is_contiguous())
                assert(shape_group.stroke_color.offsets.is_contiguous())
                assert(shape_group.stroke_color.stop_colors.is_contiguous())
                assert(torch.isfinite(shape_group.stroke_color.stop_colors).all())
                args.append(diffvg.ColorType.radial_gradient)
                args.append(shape_group.stroke_color.center.cpu())
                args.append(shape_group.stroke_color.radius.cpu())
                args.append(shape_group.stroke_color.offsets.cpu())
                args.append(shape_group.stroke_color.stop_colors.cpu())
            args.append(shape_group.use_even_odd_rule)
            # Transformation
            args.append(shape_group.shape_to_canvas.contiguous().cpu())
        args.append(filter.type)
        args.append(filter.radius.cpu())
        return args
Example #3
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)
canvas_width = 256
canvas_height = 256
circle = pydiffvg.Circle(radius=torch.tensor(40.0),
                         center=torch.tensor([128.0, 128.0]))
shapes = [circle]
circle_group = pydiffvg.ShapeGroup(shape_ids=torch.tensor([0]),
                                   fill_color=torch.tensor(
                                       [0.3, 0.6, 0.3, 1.0]))
shape_groups = [circle_group]
scene_args = pydiffvg.RenderFunction.serialize_scene(
    canvas_width=canvas_width,
    canvas_height=canvas_height,
    shapes=shapes,
    shape_groups=shape_groups,
    filter=pydiffvg.PixelFilter(type=diffvg.FilterType.hann,
                                radius=torch.tensor(8.0)))

render = pydiffvg.RenderFunction.apply
img = render(
    256,  # width
    256,  # height
    2,  # num_samples_x
    2,  # num_samples_y
    0,  # seed
    None,
    *scene_args)
# The output image is in linear RGB space. Do Gamma correction before saving the image.
pydiffvg.imwrite(img.cpu(),
                 'results/optimize_pixel_filter/target.png',
                 gamma=2.2)
target = img.clone()