Matthew ArmstrongTrace a photo, scan or drawing of a part into a clean, extrudable FreeCAD sketch: straight
Work in progress (v0.2.0-wip, built 2026-10-03 13:10). The tracing library is tested against
simulated images with known geometry. The FreeCAD side has not yet been run inside real
FreeCAD - only against stand-in modules and the OpenCascade kernel. See
What has and has not been tested.
Trace a photo, scan or drawing of a part into a clean, extrudable FreeCAD sketch: straight
lines, arcs, circles and splines, with holes, at true scale.
Left: a simulated "bad photo" (shadow, uneven light, dust, scratches, pen marks, blur, JPEG).
Right: the verdicts. Green = traced as real geometry, amber = borderline (added as construction
geometry so you can accept or delete it).
Scale comes from a printable marker sheet (also fixes perspective), from a known picture
width, from a known mm-per-pixel value, or from a plain square of known size in the picture.
python3 install.py
That copies the add-on into FreeCAD's user Mod folder (it finds FreeCAD 0.21, 1.0 and 1.1
folders on Linux, macOS and Windows) and installs OpenCV into the add-on's own _deps folder.
Restart FreeCAD, choose the ImageToSketch workbench, press Image to sketch....
Mod as ImageToSketch. The first time you
open the dialog it offers to install OpenCV for you.sudo apt install python3-opencv then
python3 install.py --no-opencv also works.python3 install.py --uninstall removes it again.Settings worth knowing:
| Setting | What it changes |
|---|---|
| Part tone | Force "dark part" or "light part" if the automatic guess is wrong. |
| If two edges compete | A hard-edged shadow (or a bevel) gives two sharp outlines. Keep the inner edge ignores the shadow; keep the outer edge is right for bevelled parts. The loser is still added as construction geometry. |
| Smallest real feature | Holes smaller than this become construction geometry; bumps shorter than this on an edge are bridged. Automatic is about 0.7 % of the picture diagonal. |
| Fit tolerance | How closely primitives must follow the edge. Automatic is 0.5 px, more if the picture is blurred. |
pip install opencv-python-headless numpy
python3 -m imagetosketch photo.jpg --markers --svg part.svg --dxf part.dxf --overlay check.png
python3 -m imagetosketch --make-sheet sheet.pdf --paper A4
python3 -m imagetosketch --help
SVG and DXF are in millimetres and import into FreeCAD, Fusion 360, Inkscape and LibreCAD.
From Python: from imagetosketch import trace, Options.
60 simulated images (12 kinds of damage x 5 random seeds), 420 true outlines, 1600 x 1200 px:
| Found | False | Mean error | Radius error | Time | |
|---|---|---|---|---|---|
| v0.1 macro (one threshold) | 370 / 420 | 436 | 0.60 px | 0.45 px | 6 ms |
| Full detector bank with voting | 411 / 420 | 364 | 0.59 px | 0.45 px | 206 ms |
| v0.2 (this) | 419 / 420 | 9 | 0.05 px | 0.03 px | 130 ms |
Times are one core of a 2.1 GHz Xeon. A 12-megapixel colour JPEG takes about 1.2 s and 160 MB of
memory (it is reduced to 2400 px first). Why this design won, and the full table, is in
docs/BENCHMARK.md.
On the simulated marker-sheet photo above (tilted camera, uneven light, noise) hole diameters
came out within 0.005 mm, fillet radii within 0.01 mm and straight-edge lengths within about
0.03 mm of the true sizes.
Tested (44 automated tests, python3 -m pytest):
tests/fake_freecad), with
the resulting geometry rebuilt in OpenCascade (FreeCAD's own geometry kernel), checked to be
closed, and padded into a solid whose volume matches the true part to 0.005 % (clean image)
and 0.06 % (the "bad photo" above).Not tested:
from imagetosketch import fc_gui; fc_gui.show().imagetosketch.fit.fit_loop has no FreeCAD or image dependency and can be reused there.imagetosketch/ the library: detect, fit, pattern, pipeline, export, cli + FreeCAD front end
InitGui.py, Init.py, package.xml FreeCAD add-on entry points
ImageToSketch.FCMacro macro that opens the dialog
install.py one-step installer
tests/ test suite, simulated scenes, stand-in FreeCAD modules
bench/ the design comparison, re-runnable
docs/ benchmark write-up, images, printable marker sheets
The usual src/main.py layout is not used because FreeCAD needs InitGui.py at the top of the
add-on folder. Heavy lifting is OpenCV (C++); the Python is glue. The dialog is Qt because it
runs inside FreeCAD.