AI-Created Software

Last Updated: September 10, 2026

The following AI-generated aka vibe-coded software. The software is specific to my needs and my system and may not work for you or your system. Support is limited, but if you report a bug I'll certainly look into it. All code is provided in a zip file for you to review should you choose.

Depth Map Reference Mask Tool

A small desktop app (Tkinter) for turning a depth map into a grayscale mask centred on a depth of your choosing.

You load a depth map, paint over the region you want to treat as the reference depth, and the tool produces an image where that depth is white and everything else fades toward black as it moves away from the reference. The falloff can be shaped independently in each direction and given a solid core, and the result can be exported as a straight grayscale mask or as a cutout of a paired color frame with the mask as its alpha channel.


Requirements

  • Python 3.8 or newer, with Tkinter available (bundled with most Python installs; on Debian/Ubuntu you may need sudo apt install python3-tk)
  • pillow
  • numpy
pip install pillow numpy

Running

python depth-map-reference-mask.py

How it works

  1. The loaded image is read as depth. Whatever the source bit depth, values are held internally as float32 on a 0–255 scale, so 16-bit input keeps its precision.

  2. The reference depth is the mean depth of every pixel you painted.

  3. Each pixel’s distance from the reference is measured, the plateau is subtracted, and what remains is divided by the falloff for that side:

    distance = max(|depth − reference| − plateau, 0)
    falloff  = near   if the pixel is on the near side of the reference
               far    if it is on the far side
    output   = (1 − min(distance / falloff, 1)) × 255

So a pixel within the plateau of the reference is fully white, a pixel a full falloff beyond the plateau is black, and anything past that is clamped to black.

Plateau widens the solid white core. With it at zero, only pixels at exactly the reference depth reach full white, which makes “solid subject, soft edges” hard to achieve. Raise it to hold a band of depth at full strength before the ramp begins.

Near and far falloff shape each side separately, so you can let the mask reach a long way behind the subject while cutting off sharply in front of it. Brighter = nearer tells the tool which direction “near” points in; leave it on for the usual convention where higher depth values are closer to camera. With it off, the two falloffs swap sides.

Auto falloff range sets both falloffs so they just reach the most distant pixel on their side, giving an output that uses the full 0–255 range in both directions. The plateau still applies — the falloffs shrink to keep the outer edge of the ramp where it was. Turn auto off to drive the two sliders yourself.


Using the app

Toolbar

Control What it does
Load Depth Image… Opens a depth map (.png, .jpg, .jpeg, .tif, .tiff, .bmp)
Load Color Image… Loads the matching RGB frame, used as the base for the RGBA cutout
Clear Painted Mask Wipes the painted region and the current result
Save Re-saves into the folder used last time; falls back to Save As… if nothing has been saved yet
Save As… Prompts for a parent folder and creates a new result folder inside it
Load Project Reopens a previously saved result from its sidecar .json
Actual Size / 2x / 0.5x / Fit to Window Zoom controls for both preview panes
Show mask overlay Toggles the red paint overlay so you can read the depth values underneath
Link pane scrolling Keeps the two panes showing the same part of the image
Brush size 2–512, with a units selector (see below)

Keyboard

Key Action
[ / ] Shrink / grow the brush, in steps of about 10%
\ Toggle the mask overlay
Ctrl+S / Ctrl+Shift+S Save / Save As
Ctrl+O Load a depth image

Painting

  • Left-click / drag — paint the reference area. A translucent red overlay shows what’s painted.
  • Right-click / drag — erase. (Middle-click is also bound to erase, since some macOS input devices send it for a secondary click.)
  • The circle following your cursor previews the brush footprint: teal when painting, red when erasing.
  • The result preview refreshes when you release the mouse button.

Brush units. In display mode the brush keeps a constant on-screen size, which feels natural but covers more source pixels as you zoom out. In source mode it covers a fixed number of image pixels at every zoom level, which is what you want for repeatable work.

Panes

The left pane shows the depth map with your painted overlay; the right shows the generated result. They share a zoom level, and with Link pane scrolling on, scrolling or mouse-wheeling either one moves the other to match — so a detail stays lined up between the two while you compare them. Turn it off to park the panes on different parts of the image.

Depth histogram

The panel along the bottom shows the distribution of depth values in the image, with the current response curve drawn over it in teal, the reference depth as a red line, the plateau as a shaded band, and the outer edge of each falloff as a dashed line. This turns the falloff sliders from guesswork into aiming: you can see which peak is your subject and how much of it the current settings actually cover.

Counts are on a log scale, because depth maps very often contain one enormous spike (a flat background) that would otherwise flatten everything else out of view.


Output

Save As… asks for a parent folder, then creates a subfolder named after the source image. If a folder with that name already exists, it appends _01, _02, and so on rather than overwriting anything.

Inside that folder, using bedroom.png as an example source:

bedroom/
├── bedroom_with_reference_set.png   # the generated grayscale result
├── bedroom_mask.png                 # the painted mask on its own (white = painted)
├── bedroom_rgba.png                 # the RGBA cutout (optional)
├── bedroom.json                     # sidecar metadata (also the project file)
├── bedroom.png                      # the source depth map
└── bedroom_color.png                # the paired color frame, if one was loaded

The source images are linked rather than copied where possible: a symlink is tried first, then a hard link, then a real copy as a last resort. Symlinks on Windows need Developer Mode or admin rights, and hard links need the source and destination to be on the same volume, so the copy fallback is what guarantees the folder is self-contained.

Bit depth

Bit depth in the Output panel selects match (follow the source), 8, or 16. A 16-bit source defaults to a 16-bit PNG result. This matters for gentle falloffs across a wide depth range, which band visibly when quantized to 256 levels.

RGBA cutout

With Export RGBA cutout ticked, the tool also writes an RGBA PNG: the color frame with the generated mask as its alpha channel — the actual cutout, ready to composite. Without a color frame loaded, the depth map is used as the RGB base instead. This export is always 8-bit; PNG can carry 16-bit RGBA but little downstream software reads it.

Sidecar JSON

Field Meaning
format_version Project schema version (currently 2)
source_image, source_image_name Absolute path and filename of the original depth map
linked_image_file, link_type The copy in the result folder, and how it was made (symlink, hardlink, copy, unchanged, or null)
color_image, linked_color_file, color_link_type The same, for the paired color frame
image_width, image_height Source dimensions in pixels
source_bit_depth Bit depth detected in the source (8, 16 or 32)
output_bit_depth Bit depth this result was written at
output_bit_depth_choice The setting itself (match, 8 or 16)
reference_depth Mean depth under the painted mask, 0–255
reference_depth_16bit The same value on a 0–65535 scale
auto_falloff_range Whether auto falloff was active
bright_is_near Which depth direction was treated as near
falloff_near, falloff_far The two falloff values actually used
falloff_range max(near, far), kept so v1 readers still work
plateau Plateau width
brush_size, brush_units Brush settings at save time
mask_file, result_file, rgba_file Filenames of the other outputs
painted_pixel_count Number of painted pixels
painted_coverage_pct Painted pixels as a percentage of the image
painted_bounding_box x_min/y_min/x_max/y_max of the painted area, or null
generated_at ISO 8601 timestamp

Reopening a project

Load Project takes one of these .json files (or a folder containing one) and restores the depth map, the color frame, the painted mask, the brush settings and the full falloff shape, then regenerates the preview.

It looks for the images next to the project file first and only then at the absolute path recorded inside it, so a result folder still opens after being moved, renamed, copied to another drive or handed to someone else — provided the local copies are real files or hard links rather than symlinks pointing at a since-deleted original. Sidecars written by the previous version load fine: their single falloff_range is applied to both sides and the plateau starts at zero.

The heading above the result pane reads (unsaved) or (saved as <path>) so you can tell at a glance whether the preview matches what’s on disk, and closing the window with unsaved work prompts you to save, discard or cancel.


Persisted app settings

The app writes depth-map-reference-mask.ini next to the script, storing window geometry and maximized state, the last folders used for loading and saving, and your overlay, pane-link, brush-unit, bit-depth and RGBA-export preferences. Deleting the file resets the app to its defaults.

Optional icon files

If you want a custom title-bar and taskbar icon, place these alongside the script:

depth_mask_app.ico
Resources/depth_mask_app_icon_16.png
Resources/depth_mask_app_icon_32.png
Resources/depth_mask_app_icon_64.png

All of it is optional. Missing or unreadable icons print a one-line note to the console and the app falls back to the default Tk icon.

On Windows the app also sets an explicit AppUserModelID (so the taskbar shows the app’s icon instead of python.exe’s) and marks itself DPI-aware (so “Actual Size” really is 1:1 under display scaling above 100%).


Notes and limitations

  • EXR files are not supported. Pillow can’t read them without an OpenEXR plugin; convert to 16-bit PNG or TIFF first.
  • 32-bit float depth maps are accepted, but since the format carries no inherent range the tool sniffs it from the data (0–1, 0–255, or 0–65535). Check the result if your data uses some other range.
  • The mask is hard-edged. Brush stamps aren’t anti-aliased, and every painted pixel counts equally toward the reference average, so a stroke that clips an edge will drag the reference with it.
  • No undo. Right-click erase is the way back; “Clear Painted Mask” starts over.
  • The falloff ramp is linear. There’s no gamma or curve control, so the transition can read harshly in a composite.
(1 votes, average: 5.00 out of 5)

Leave a Reply

Your email address will not be published. Required fields are marked *

Notify me of followup comments via e-mail.