What The Silhouettes Actually Does
The Silhouettes is a Python-based pipeline for extracting clean object boundaries from images, then vectorizing them into SVG or DXF formats. It sits somewhere between OpenCV contour detection and manual tracing in a CAD program. You feed it a raster image, it returns a clean vector edge map. That is the whole thing. I have been using it on production runs for about two years, mostly for converting engineering drawings and scanned floor plans into editable line work. It is not the prettiest tool out there, but it gets the job done faster than doing it by hand. The output is usually good enough that I only spend a few minutes cleaning up stray nodes before moving on. Here is the thing nobody tells you about it upfront: The Silhouettes does not do inpainting. If your source image has gaps or noise inside the region you want to trace, the algorithm will either break the contour or create a bunch of tiny spurious paths. I ran into this hard with a set of 1990s photocopies where the toner had flaked off along the edges of certain structural lines. The default pipeline produced about forty fragmented segments for what should have been a single continuous boundary.
The workaround I ended up using was surprisingly simple. Before feeding anything into The Silhouettes, I run a morphological close operation with a kernel size of roughly 3x3 pixels using OpenCV's cv2.morphologyEx() with the MORPH_CLOSE flag. Then I threshold again at whatever adaptive level your image needs. This bridges the tiny gaps without thickening the lines too much. After that, the silhouette extraction stage picks up clean paths every time. It adds maybe ten seconds to the preprocessing step, but it saved me from spending hours fixing garbage output.
Installing The Silhouettes
The package lives on PyPI under the name silhouettes-extract. You can grab it with pip, though I recommend using a virtual environment first because it pulls in Pillow, scikit-image, and shapely, which sometimes fight with each other depending on what else you have installed. pip install silhouettes-extract On Windows, you may also need the Microsoft Visual C++ Redistributable if the compiled extension does not find the right runtime. I learned that the hard way on a fresh build machine. The error message is vague and points at a missing DLL that has nothing to do with the package itself. Once the redistributable is in place, installation completes cleanly.
Get the Full Details
How It Actually Works Under the Hood
The pipeline runs through three stages. First it converts the input to grayscale and applies a Canny edge detector with thresholds tuned to your image content. Second it finds contours using a modified Marching Squares approach that prefers smooth curves over jagged polygon approximations. Third it simplifies and exports to your chosen format. The simplification step uses the Ramer-Douglas-Peucker algorithm, but with a dynamic epsilon value that scales to the image resolution rather than a fixed pixel distance. This means a 4K image and a 72dpi scan of the same drawing produce roughly similar path densities, which is actually useful in practice. Most tools I have seen fix the epsilon at a single value and then you are guessing whether 0.5 or 2.0 will look right. One counter-intuitive detail: The Silhouettes treats white regions as empty space and dark regions as solid, which is the opposite of how most medical imaging tools work. If you are feeding it binary masks generated from segmentation networks, make sure the foreground is black on white, not the reverse. I wasted about three days debugging an issue where my U-Net output was producing inverted boundaries because the training data used the standard convention.
Another nuance people miss is that the export stage supports multi-line output natively. You do not need to post-process individual contours to join them. Just set join_threshold to a value slightly larger than your line thickness in pixels, and nearby colinear segments get merged automatically. In my experience this cuts the cleanup phase from maybe twenty minutes down to three or four.
Real-World Usage
Here is a minimal script that processes a batch of engineering drawings: import silhouettes as sio This processes a typical A1 drawing in about 8 to 12 seconds on a mid-range laptop, depending on image complexity. A dense architectural plan with lots of hatching and text annotations might take 30 seconds to a minute because the edge detector picks up far more contours to process.
pipeline = sio.Pipeline(simplify=True, join_threshold=1.5)
for f in glob.glob("drawings/*.png"):
out = pipeline.run(f, output_format="dxf")
out.save(f.replace(".png", ".dxf"))

If you need faster turnaround, you can preprocess with cv2.fastNlMeansDenoisingColored() to reduce noise before edge detection. This usually brings processing time down by about 20 percent and improves contour continuity, especially on scanned documents with paper texture or compression artifacts. There are also some rough edges worth knowing about. The DXF exporter does not handle overlapping polylines well. If your image contains details where two objects share an edge, like a wall meeting a floor line, the output sometimes produces duplicated vertices at the intersection. I worked around this by running a small custom post-process that snaps nearby vertices within a tolerance of 0.001 units, which removes the duplicates without changing the geometry in any meaningful way. Another limitation: The tool does not support 3D point clouds or LIDAR data directly. It is strictly 2D image based. If you need silhouettes from volumetric data, you have to project or slice first, then feed the result into the pipeline. This is obvious in retrospect but took me by surprise when I tried piping raw .ply files into it and got a confusing type error.
The community is small. There is a GitHub repo with issues and pull requests, but updates are slow. The last major release was about eight months ago, and the maintainers seem to use it internally rather than treating it as a commercial product. This is fine if you just need it to work. It is less fine if you want new features shipped quickly or official support for edge cases. For production work I usually pair it with a simple quality check script that counts the number of contours per output file and flags anything above a threshold as suspicious. When the count spikes, it usually means the preprocessing step missed something and the edge detector went wild on noise. Catching it early saves more time than trying to fix the output after the fact.