Home (All Topics) → Technology → Software → AI-Created Software
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.
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.
sudo apt install python3-tk)pillownumpy
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.
The reference depth is the mean depth of every pixel you painted.
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.
| 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) |
| 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 |
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.
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.
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.
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 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.
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.
| 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 |
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.
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.
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%).


Leave a Reply