alexandre01 / deepsvg

[NeurIPS 2020] Official code for the paper "DeepSVG: A Hierarchical Generative Network for Vector Graphics Animation". Includes a PyTorch library for deep learning with SVG data.
https://www.reshot.ai
MIT License
972 stars 98 forks source link

Feature request: support transform #11

Open naoto0804 opened 4 years ago

naoto0804 commented 4 years ago

SVG files use usually contain transform tags like the following, but the current library does not seem to support it (as long as I see in svg.py).

<g transform="rotate(-10 50 100) translate(-36 45.5) skewX(40) scale(1 0.5)">

Is there any plan to support?

tsaxena commented 3 years ago

I also looked around and could not find support for groups in general. @alexandre01 Do we have to turn groups into simple paths for using the network?

pwichmann commented 3 years ago

As a workaround, you could create a script to automate Inkscape and apply it to your SVG input folder as a preprocessing step. https://github.com/Klowner/inkscape-applytransforms

Have not tried it myself though.

tsaxena commented 3 years ago

Thanks @pwichmann . I will try that out.

For now, I figured out that the problem is NOT groups. I loaded an svg with groups and the current code base did load the svg correctly, except that I had to add "fill = "none" to each path in the group, otherwise when it draws its all black. I am now trying to see if in that case the conversion to tensor is right. Is there a way of converting an tensor back to svg to make sure its working correctly?

alexandre01 commented 3 years ago

Hello @tsaxena,

I recently added a Dataloader which can directly handle SVG icons as input. You can first pre-process the entire dataset using the https://github.com/alexandre01/deepsvg/blob/master/dataset/preprocess.py script or load https://github.com/alexandre01/deepsvg/blob/master/deepsvg/svg_dataset.py with already_preprocessed=False to perform preprocessing on the fly.

The preprocessing does the following:

svg.fill_(False)
svg.normalize().zoom(0.9)
svg.canonicalize()
svg = svg.simplify_heuristic()

Indeed, if you want to train a model for strokes only (without taking filling into account), you can set fill to False.

alexandre01 commented 3 years ago

Let me just give some clarification regarding filling. Let's take the example of a filled "donut" shape: a filled circle with a "hole" inside. This is done in SVG by drawing in the same < path > a circular shape followed by another smaller circle drawn in the opposite direction (counter-clockwise). This is the even-odd rule.

DeepSVG however draws every path separately, and would generate in this case two paths. But how to apply the correct filling? The approach we propose is to predict a fill parameter which can take one of three values: Filling.OUTLINE (for stroke only), Filling.FILL (to fill the path) and Filling.ERASE (to "unfill" that area).

During preprocessing, paths are separated but the correct "fill" parameter is memorized. However, when visualising it, all filled shapes appear black.

The SVG.group_overlapping_paths method tackles this issue and re-maps the generated outputs to a valid SVG with even-odd fill rule. It does so by analysing overlaps between shapes and their fill parameters to group them together in a common path. This is a hack though, as this approach won't work for more complex cases.

It's therefore better to stick with strokes for the moment. Hope this helped.