Rebuilds a raster logo as clean vector geometry — no Inkscape, no autotrace — by fitting straight edges with least squares and verifying the result against the original mask by IoU.
The source file was a 955×955 PNG. That is fine on screen and useless for large-format print: a printer wants outlines, and blowing up a bitmap gives a ragged edge. Autotracing a raster gives technically-vector output whose "straight" edges wobble by a pixel or two and whose corners are polygon fans. Since this particular mark is made of straight lines, circular corner fillets and 180° rotational symmetry, it is cheaper and more exact to measure those parameters off the raster and re-emit the shape parametrically.
The mark is two interlocking arrows. Only one of them is described; the second is the first rotated 180° about the centre of symmetry — verified against the original at IoU = 1.0000, so the raster really was symmetric and half the geometry is free.
For the one arrow:
- Straight edges are recovered by least-squares line fits over the mask boundary, stored as
x = k·y + apairs (tail diagonal, upper and lower head edges) plus four axis-aligned constants. Residual under 0.6 px. Vertices are then computed as line intersections rather than read off pixels — the corner is where the two fitted edges meet, which is more accurate than any single boundary pixel. - Corner radii are not measurable directly, so they are searched:
round_path()re-emits the contour with a given radius vector, replacing each vertex with tangent points and an SVG arc between them (sweep direction from the cross product of the two edge directions), and the radii are tuned to maximise IoU against the original mask. Best fit IoU = 0.9933 with one vertex left as a hard corner. - The fold shadow on the tail is a curve, not a line, so its boundary is approximated by a
single cubic Bézier at RMS = 0.5 px. Its gradient axis was recovered by regression over the
shaded pixels, and the shadow is clipped by the arrow contour via
clipPathinstead of being cut to shape.
Output is a self-contained SVG in two variants: logo_flat.svg (flat fills, for anything that
must survive a dumb renderer) and logo.svg (with the two shadow gradients). The print-ready PDF
in this directory was produced by printing the SVG through headless Chrome — the script itself
emits only SVG.
Python 3, standard library only (math). No dependencies, no image libraries at runtime — the
measurement pass was done once and its results are baked in as constants at the top of the file.
python3 build_logo.py # → logo_flat.svg + logo.svg, prints vertices and radii
python3 build_logo.py 29,30,29,32,0,9.5,80,32 # override corner radii (in vertex order)The radii argument exists because that is the one parameter that was fitted rather than measured; passing a vector lets you re-run the IoU comparison against a different rasterisation.
Colours, geometry constants, the symmetry centre and the shadow control points are all module-level constants — retargeting this to a different mark of the same construction means replacing those numbers, not the code.
build_logo.py is written for one specific logo, not as a general vectoriser. It is here as a
worked example of the approach: measure the primitives, re-emit them parametrically, and use IoU
against the original as the acceptance test instead of eyeballing the result.