Package: pixels2svg
pixels2svgv0.2.2Convert pixels to SVG square-based shapes.There are a few open source tools around that do bitmap -> vectortracing,
for instancepotracewhich is the engine
used byInkscapeand also has available python
bindings (pypotrace).But sometimes, what you want is the exact bitmap data, but as a set of
SVG shapes, that you could for instance:enlarge for big printsuse as input paths for a wood laser cuttercustomize in a vector graphics software (edit opacity, contours, overlay
on some background image etc.)Medical image segmentation is another typical use case where one has
pretty low-res images and sometimes needs to display them best for data
visualization/presentation purposes. In this case, an SVG overlay with
editable contours and opacity can be convenient.This package enables you to easily convert your bitmap image to its
equivalent SVG representation, each path of the SVG being a polygon made of
adjacent pixels of same color merged together.It is inspired ofFlorian Berger'spixel2svgpackage
(GitHub fork availablehere),
which is pretty old (python2) and doesn't merge adjacent pixels of same color,
making the SVG pretty tedious to edit in vector graphics softwares.RequirementsPython >=3.7DependenciessvgwritePILscipycc3dInstallpip install pixels2svgor directly from Github:pip install git+git://github.com/ValentinFrancois/pixels2svg#egg=pixels2svgUsageCLIpython3 -m pixels2svg [-h] [--output <path>] [--color_tolerance <int>] [--remove_background]
                      [--background_tolerance <float>] [--maximal_non_bg_artifact_size <float>]
                      [--no_group_by_color] [--no_pretty]
                      <input_path>

pixels2svg CLI

positional arguments:
  <input_path>          Path to the input bitmap image (anything supported by PIL.Image).

optional arguments:
  -h, --help            Show this help message and exit
  --output <path>, -o <path>
                        Path to the output SVG image.
                        If not passed, will print the output in the terminal.
  --color_tolerance <int>, -c <int>
                        Color tolerance (1 = the smallest luminosity difference i.e. a difference of 1 on the
                        Blue channel).
  --remove_background, -b
                        If the input image has a solid background, will try to remove it.
  --background_tolerance <float>
                        (Only relevant when `remove_background = True`)
                        Arbitrary quantity of blur use to remove noise - just fine-tune the value if the
                        default (1.0) doesn't work well.
                        0 means no blur will be used.
  --maximal_non_bg_artifact_size <float>
                        (Only relevant when `remove_background = True`)
                        When a blob of pixels is clone enough to the detected image contours and below this
                        threshold, it won't be considered as background.
                        Combined with `background_tolerance`, this allows you to control how progressive the
                        background detection should be with blurred contours.
                        Size is expressed in % of total image pixels.
  --no_group_by_color   Do not group shapes of same color together inside <g> tags.
  --no_pretty           Do not pretty-write the SVG code.In PythonSimple usagefrompixels2svgimportpixels2svgpixels2svg('input.png','output.svg')pixels2svg()accepts a few optional arguments that should help you
integrate it best within your codebase:Parametersinput_path:strPath of the input bitmap imageoutput_path:Optional[str]Path of the output SVG image (optional). If passed, the function will return None.If not passed, the function will return the SVG data as astror aDrawingdepending on theas_stringparameter.group_by_color:boolIf True (default), group same-color shapes under SVG elements.color_tolerance:intOptional tolerance parameter that defines if adjacent pixels of close colors should be merged together in a single SVG shape.Tolerance is applied based on luminosity. 1 represents the smallest difference of luminosity, i.e. a difference of 1 in the Blue channel.remove_background:boolIf True, tries to remove the background before the conversion to SVG (default False).Simple technique based on contour detection, probably won't work well with complex images.background_tolerance:float(Only relevant when remove_background = True)Arbitrary quantity of blur use to remove noise - just fine-tune the value if the default (1.0) doesn't work well.0 means no blur will be used.maximal_non_bg_artifact_size:float(Only relevant when remove_background = True)When a blob of pixels is clone enough to the detected image contours, and below this threshold, it won't be considered as background.Combined with background_tolerance, this allows you to control how progressive the background detection should be with blurred contours.Size is expressed in % of total image pixels.as_string:boolIf True and nooutput_pathis passed, return astrrepresenting the SVG data.pretty:boolIf True (default), output SVG code is pretty-printed.ReturnsOptional[Union[svg.Drawing, str]]Depends on theoutput_pathandas_stringparametersAdvanced usageBy settingoutput_path=Noneandas_string=False, you can get an object
inheritingsvgwrite.Drawing,
with the additional useful methods:def save_to_path(self, path: str, pretty: bool = False)def to_string(self, pretty: bool = False) ‑> strThis gives you access to thesvgwriteAPI to modify the output programmatically.See advanced examples inexamples.ExamplesExample 1 - vectorize and edit pixel art (source)FilePreviewOriginal PNG image(32×32)Original PNG image(browser enlarged)Output SVG imageOutput SVG image withcustomized contour styleExample 2 - brain scan + segmentation overlay (source)FilePreviewScan image (PNG)Segmentation overlay (PNG)Converted SVG segmentation overlayConverted SVG overlayed on PNG scanwith customized opacity & contour styleExample 3 - vectorize pixel art and remove background (source)FilePreviewOriginal PNG image(256×256)Output SVG image(background removed)Example 4 - vectorize sprite with gradients and reduce number of colors  (source)FilePreviewOriginal PNG image(150×150)Output SVG image(color tolerance:0)Output SVG image(color tolerance:64)Output SVG image(color tolerance:128)Output SVG image(color tolerance:256)Output SVG image(color tolerance:512)LimitationsThe code isn't optimized and runtime is pretty much proportional to the
dimensions and the number of colors of the image that gets traced in SVG:
we indeed iterate over each isolated color blob to calculate its polygonal
contour. This is why reducing the number of colors might be useful.For instance, converting the 150×150 fireball sprite with transparency inexample 4took 60s on my laptop.Usingcolor_tolerance=64, it took 4s. Usingcolor_tolerance=128, it took 0.8s.