dvi3v - extract object from photo and create filled SVG with real dimensions
dvi3v [OPTIONS] INPUT_IMAGE OUTPUT_SVG
dvi3v (Dvitiya-Vimatra-Varna-Vikasa-Vinyasa) detects an object in the center of a photograph, extracts its contour, fills it with a solid color, and generates an SVG file with real-world dimensions in millimeters.
The tool uses a reference paper sheet (default: A4) visible in the image to calculate accurate scale conversion from pixels to millimeters.
-c, --color COLOR
Fill color for the object. Can
be a color name (e.g., red, blue, green) or hex code (e.g.,
#FF0000).
Default: black
Supported color names: black, white, red, green, blue, yellow, cyan, magenta, gray (or grey), darkgray (or darkgrey), lightgray (or lightgrey), orange, purple, pink, brown, darkred, crimson, darkblue, navy, skyblue, lightblue, darkgreen, lime, olive
-m, --margin-mm MM
Margin around the object in
millimeters.
Default: 2.0
Typical values:
0-0.5: Precise contour
1.0-2.0: General use
3.0-5.0: Manufacturing/cutting tolerance
8.0-10.0: Large margin
-t, --threshold PERCENT
Detection threshold (0-100%).
Lower values detect darker objects, higher values detect
lighter objects.
Default: 50
Guidelines:
30-40: Very dark objects
40-50: Normal objects
50-60: Light-colored objects
60-70: Very light objects
-a, --auto-threshold TRIES
Automatically optimize
threshold by testing N values (2-20) between 30% and 80%.
Selects the best based on quality scoring.
Default: disabled (uses manual threshold)
Recommended
values:
5: Quick optimization (sufficient for most cases)
7: Balanced precision and speed
10: Maximum precision (slower)
-n, --no-holes
Fill only the outer contour, ignoring internal holes. Useful for objects like scissors (fills handle holes), keys, or letters with holes (O, P, A).
Without this option, internal holes are preserved in the SVG.
|
--dxf |
Also write a DXF file beside the SVG (same basename, .dxf), in millimetres. Produced with potrace’s native DXF backend; no extra dependency. Useful for CAD and CNC import. |
--stl [METHOD]
Also write an extruded STL beside the SVG (same basename, .stl): the silhouette is extruded to a flat plate. METHOD is python (the default) or scad. The python backend needs only python3 (it uses the bundled StlExtrude helper and triangulates with a vendored earcut), so an end user does not need OpenSCAD. The scad backend uses openscad. If the requested backend is unavailable the other is used as a fallback; if neither is present the STL is skipped with a warning and the SVG is still produced.
--stl-thickness MM
Extrusion thickness for the STL, in millimetres (default: 3.0). Implies --stl.
-r, --reference-mm SIZE
Manual scale override: skip paper detection entirely and derive the pixels-per-millimetre scale from SIZE directly.
What SIZE
means: SIZE is not the dimension of any
particular object or edge that the script looks for in the
photo. Instead, the script assumes that 70% of the
photo’s height (in pixels) corresponds to
SIZE millimetres in the real world, and computes the
scale from that alone:
scale (px/mm) = (image_height_px × 0.70) / SIZE
Concretely: give as SIZE the real-world height, in mm, of whatever vertical span you intend to occupy roughly the middle 70% of the frame --- typically the reference paper’s long edge if you framed the paper to fill most of the photo height, since that is what paper detection would otherwise have measured. This is a coarse substitute for actual detection: it assumes your framing, not a measurement, so accuracy depends entirely on how closely the true subject height matches 70% of the frame.
Worked
example: a 3000×4000px photo (height 4000px) with
-r 297 (A4 height in mm):
estimated_px = 4000 × 0.70 = 2800px
scale = 2800 / 297 ≈ 9.4276 px/mm
That scale is then applied to the detected object’s pixel size to get its millimetre dimensions in the output SVG --- it does not change how the object itself is detected, only how its pixel measurements are converted to millimetres.
Use when reference-paper detection fails or no reference paper is used at all (see PAPER DETECTION AND COLOR below for why detection can fail even with a paper visibly in frame).
-p, --paper-format FORMAT
ISO paper format for scale
reference.
Default: A4 (210×297mm)
Supported
formats:
A0: 841×1189mm A1: 594×841mm A2: 420×594mm
A3: 297×420mm A4: 210×297mm A5: 148×210mm
A6: 105×148mm
Letter: 216×279mm (8.5×11 inches)
Legal: 216×356mm Tabloid: 279×432mm
-P, --paper-color COLOR
Color of reference paper for
improved detection.
Default: automatic color detection (see below);
"white" only if this option is given explicitly as
--paper-color white
Any color name accepted by --color can be given here (see -c for the list). Giving this option skips automatic color detection and matches against exactly the named color instead --- useful if automatic detection picks the wrong color, or to avoid its extra processing time. See PAPER DETECTION AND COLOR below for how detection works.
-d, --debug [DIR]
Keep intermediate debug images and show detailed execution logs.
If DIR is specified, debug files are saved to that directory (will be created if it doesn’t exist). Otherwise, files are saved in a temporary directory /tmp/dvi3v-PID (path displayed on start). User-specified directories are never automatically deleted.
Debug files
created:
debug_0_paper_detect.png: Paper detection result
debug_1_binary.png: Object detection binary
debug_2_cropped.png: Cropped object region
debug_2b_cleaned.png: After cleaning (--no-holes only)
debug_2c_filled.png: After hole filling (--no-holes only)
debug_3_final.pbm: Final bitmap with margin
-b, --batch [ACTION]
Enable batch mode for automated processing without user prompts.
When no reference paper is detected, batch mode does not pause for user confirmation.
Optional
ACTION argument:
continue: Process with estimated scale (default)
abort: Exit with error if no reference detected
Use "continue" for automated workflows where approximate dimensions are acceptable. Use "abort" for quality control that requires accurate measurements.
--list-paper-formats
Print the supported ISO/US paper formats and their dimensions in millimetres, then exit. Does not process an image; the INPUT_IMAGE and OUTPUT_SVG arguments are not required with this option.
-h, --help
Display help message and exit.
-v, --version
Display version information and exit.
Basic usage (black object, 2mm margin, A4 white paper)
dvi3v photo.jpg object.svg
Red object with 3mm margin
dvi3v -c red -m 3.0 photo.jpg object.svg
Custom hex color with 2.5mm margin
dvi3v --color ’#2C3E50’ --margin-mm 2.5 photo.jpg object.svg
Auto-optimize threshold (try 7 values)
dvi3v -a 7 photo.jpg object.svg
Scissors with holes - fill handle openings
dvi3v -n scissors.jpg scissors.svg
Combine auto-threshold and no-holes
dvi3v -a 7 -n scissors.jpg scissors.svg
Use A3 format with blue paper reference
dvi3v --paper-format A3 --paper-color blue photo.jpg object.svg
Debug mode to inspect intermediate steps
dvi3v -d photo.jpg object.svg
Force scale with known dimension
dvi3v -r 297 photo.jpg object.svg
Batch processing (continue with estimated scale if needed)
dvi3v --batch photo.jpg object.svg
Batch processing with abort on missing reference
dvi3v --batch abort photo.jpg object.svg
Automated batch processing with auto-threshold
for img in *.jpg; do dvi3v --batch -a 5 $img ${img%.jpg}.svg ; done
For best
results:
Essential
• Place object
approximately in CENTER of frame
• Ensure sufficient CONTRAST with background
• Object fully visible (not cut off)
Recommended
• Include reference paper
(A4, Letter, etc.) in image
• Use uniform lighting (diffuse, not harsh shadows)
• Keep camera parallel to surface (minimize
perspective)
• Reference paper should not cover the object
Not Required
• White background (any
background works)
• Perfect lighting
• Controlled environment
• Pure white paper --- light-colored paper works too,
see below
Reference-paper
detection uses up to three methods, tried in order:
1. Automatic color detection
(used whenever --paper-color is not given at all). The photo is reduced to its dominant colors by color clustering (ImageMagick’s built-in color quantization: pixels are grouped into a small number of representative color clusters, the way a k-means-on-RGB pass would), the same way an image editor’s "reduce colors" feature works. Each large-enough cluster --- largest first --- is then tried as a paper-color candidate through method 2 below. This is what lets colored paper (e.g. a red sheet) work with no flags at all; the discovered color is reported, e.g. (auto-detected color #D63B44).
2. Named color match
(used when --paper-color names anything other than a neutral gray: white, gray/grey, lightgray/lightgrey, darkgray/darkgrey, or black; also used internally by method 1 for each candidate color). The photo is matched against an RGB color (the named-color table --color uses, see -c, or a cluster’s own color for method 1), with tolerance for real-world lighting, paper stock, and camera white balance. This finds paper by hue and works even for a saturated, visually dark-in-luminance color like red, which the brightness method (below) cannot see at all.
3. Brightness match
(used for a neutral --paper-color, and as the final fallback if methods 1–2 find nothing valid). The photo is converted to grayscale and searched for the largest bright region of roughly the right aspect ratio for --paper-format. This is the right tool for neutral paper, where "paper" and "bright" mean the same thing, but it is blind to hue: a saturated color such as red typically photographs at only 25–35% grayscale luminance --- similar to or darker than an ordinary work surface --- so it can be missed by brightness matching even though it looks highly contrasted to a human eye next to a light-colored object.
Neither -t nor -a affects any of this: those control object detection, not paper detection.
Practical effect: colored paper is usually detected automatically, with no flags needed. If automatic detection picks the wrong dominant color (e.g. the object or background is larger or more uniform in color than the paper), give --paper-color explicitly to skip straight to method 2, e.g. --paper-color red for red paper. Detection debug images (see -d) are named paper_detect_color_autoN_*.png for automatic candidate number N (method 1), paper_detect_color_named_*.png for an explicit --paper-color (method 2), and paper_detect_*.png (no color_) for brightness match (method 3).
If detection still fails after all methods, batch mode falls back to an EXIF-based scale estimate (subject distance and focal length, when the camera recorded them), typically accurate only to ±10–30%. For guaranteed accurate dimensions regardless of paper color, use -r/--reference-mm to supply a known dimension directly and skip paper detection altogether.
When using -a/--auto-threshold, the script:
1. Tests N
threshold values evenly distributed from 30% to 80%
2. For each threshold, detects objects and calculates
quality score
3. Selects threshold with highest quality score
Quality
Scoring (0-100 points):
• Centrality (20 pts): Object near image center
• Size Ratio (20 pts): Optimal 10-40% of image area
• Compactness (15 pts): Not too elongated
• Fill Ratio (30 pts): Solid object vs fragmented
• Threshold Stability (15 pts): Prefer moderate values
(45-65%)
The stability factor prevents selecting extreme thresholds that might clip object edges or include artifacts.
The generated
SVG contains:
Dimensions
Real-world measurements in millimeters (width/height attributes)
Metadata (in comments)
• Generator version
• Threshold used (manual or auto-optimized)
• Mode (with/without holes)
• Scale factor (px/mm) and detection method
• Reference paper format and color
• Object dimensions
• Margin applied
• Fill color
Content
Single SVG <path> element with filled object silhouette
|
0 |
Success |
|||
|
1 |
Error occurred (see error message for details) |
With the
enhanced error handling in v2.0+, error messages include:
• Line number where error occurred
• Function name being executed
• Command that failed
• Call stack (for nested functions)
/tmp/tmp.XXXXXX
Temporary directory for intermediate files (deleted unless -d flag used)
No special environment variables required.
paper-detected
Reference paper found automatically (most accurate)
user-reference
User provided dimension with -r option
estimated
Paper not found, scale estimated (warning shown, ˜10% error possible)
Fills interior holes by a topological exterior flood-fill: the background is flooded inward from the image border, and any region the flood cannot reach is an enclosed hole and is filled. This fills enclosed holes of any size and shape and leaves the outer contour unchanged. Channels that are open to the object’s outline (not fully enclosed) are not filled, since they are part of the exterior.
May fill
legitimate holes in objects like:
• Eyeglass frames (lenses)
• Picture frames (interior)
• Hollow letters
For these cases, omit -n or post-edit in vector graphics software.
Report bugs to Peter Felecan <pfelecan@gmail.com>
Known
limitations:
• Single object detection: among plausible candidates
(not covering most
of the frame), the one closest to center wins; a second real
object in
frame is not reported separately
• Requires minimum contrast
• Reference paper should be visible for accurate scale
• Automatic paper-color detection (see PAPER
DETECTION AND COLOR above) can pick the wrong dominant
color if the object or background is larger or more
uniformly colored than the paper; give --paper-color
explicitly if so
Written by Peter Felecan with assistance from Claude (Anthropic AI).
Copyright ©
2026 Peter Felecan, with Claude (Anthropic AI), model Sonnet
5
License: GNU General Public License v3.0 or later
This is free software: you are free to change and
redistribute it.
convert(1), identify(1), potrace(1), inkscape(1)
Full documentation: <project documentation URL>
Project name:
dvi3v (Dvitiya-Vimatra-Varna-Vikasa-Vinyasa)
Sanskrit meaning:
"Second-Dimension-Color-Development-Layout"