# Internal Architecture of the Depth Map Generation Process in mcp_3d_relief

> Explore the internal architecture of depth map generation in mcp_3d_relief. Discover its dual-path process converting images to height fields for STL mesh extrusion.

- Repository: [bigchx/mcp_3d_relief](https://github.com/bigchx/mcp_3d_relief)
- Tags: internals
- Published: 2026-02-26

---

**The mcp_3d_relief repository implements a dual-path depth map generation process that converts visual images into grayscale height fields through either a fast luminance pipeline (default) or an advanced gamma-corrected algorithm, both feeding into STL mesh extrusion.**

The depth map generation process is the foundational transformation step in the 3-D relief conversion pipeline. As implemented in the bigchx/mcp_3d_relief repository, this architecture separates image handling, depth calculation, and mesh generation into distinct stages. Understanding these internals reveals how the system balances processing speed against depth accuracy when converting 2D images into printable 3D models.

## Architecture Overview

The depth map generation architecture follows a modular pipeline design that isolates input handling from depth calculation logic. At the highest level, the `relief()` function in [`relief.py`](https://github.com/bigchx/mcp_3d_relief/blob/main/relief.py) orchestrates the workflow by first acquiring the source image, then routing to one of two depth processing strategies based on the `skip_depth` parameter. This boolean flag determines whether the system uses the built-in simple depth converter or delegates to the more sophisticated `generate_depth_map()` function. The resulting 8-bit grayscale array is persisted to disk before being passed unchanged to `generate_stl()` for mesh extrusion.

## Image Acquisition and Input Normalization

Before any depth calculation occurs, the system normalizes diverse input sources into a consistent PIL Image object. The `relief()` function accepts three input types: local file paths, HTTP/HTTPS URLs, or pre-loaded `PIL.Image` instances.

For URL inputs, the system downloads the image asynchronously using `aiohttp`. For local files, it validates the path through `os.path.isfile()`. Once loaded, the image enters the depth processing pipeline regardless of its original source format. This normalization layer ensures that downstream depth algorithms receive a standardized RGB or RGBA image buffer.

## The Two-Stage Depth Map Pipeline

The repository implements a bifurcated depth map generation strategy that trades processing complexity for quality. The choice between paths is controlled by the `skip_depth` parameter passed to `relief()`.

### Simple Depth Path (Default)

When `skip_depth=False` (the default), the system executes a streamlined depth extraction directly within `relief()` (lines 176–236). This path prioritizes speed through minimal transformations:

1. **Grayscale Conversion** – The input image converts to 8-bit luminance via `input_image.convert("L")` and transforms into a NumPy array.
2. **Resolution Scaling** – The array resizes to a target dimension calculated as `320 * detail_level`, allowing users to control output fidelity.
3. **Noise Reduction** – A light Gaussian blur with a 3 × 3 kernel and σ = 0.8 smooths intensity transitions.
4. **Optional Inversion** – If `invert_depth=True`, the system flips the height values using `255 - depth_map`, converting peaks to valleys.

This path excels for high-contrast images where simple luminance correlates directly with perceived depth.

### Advanced Depth Path (`generate_depth_map`)

Setting `skip_depth=True` triggers the advanced pipeline via the dedicated `generate_depth_map()` function (lines 25–49). This algorithm applies photographic processing techniques for more nuanced depth perception:

1. **Aspect-Preserving Resize** – The image scales so its longer side matches `320 * detail_level`, maintaining geometric proportions while standardizing pixel dimensions.
2. **Weighted Luminance** – For RGB inputs, the converter applies standard Rec. 601 coefficients: `0.299 R + 0.587 G + 0.114 B`.
3. **Gamma Correction** – A nonlinear transformation (`np.power(gray / 255.0, 1.5) * 255`) compresses shadow values and expands highlight detail, mimicking human depth perception.
4. **Aggressive Smoothing** – A 5 × 5 Gaussian kernel with σ = 1.5 reduces noise more effectively than the simple path.
5. **Inversion Control** – The same `invert_depth` logic applies as `255 - gray` when enabled.

The function returns an 8-bit `uint8` array optimized for high-fidelity STL generation.

## Post-Processing and Persistence

Regardless of which generation path executes, the resulting depth map array undergoes standard finalization. The system writes the grayscale array to disk using `cv2.imwrite()` with a `*_depth_map.png` filename pattern. This persistence step serves dual purposes: it provides users with a previewable intermediate artifact and creates a cached asset that the STL generator can reference. The 8-bit unsigned integer format (`uint8`) ensures compatibility with both OpenCV operations and the subsequent mesh generation algorithms.

## Integration with STL Generation

The depth map generation process culminates in passing the finalized 8-bit array to `generate_stl()`. This function interprets each pixel intensity (0–255) as a Z-axis extrusion height, where 0 represents the base plane and 255 represents maximum elevation (or the inverse if `invert_depth` was applied). The modular boundary between depth generation and mesh creation allows developers to swap depth algorithms without modifying the STL triangulation logic, maintaining stable mesh topology regardless of the input processing method.

## Summary

- **Dual-path architecture** – The `relief()` function offers a `skip_depth` toggle that selects between a fast built-in converter (lines 176–236) and the advanced `generate_depth_map()` implementation (lines 25–49).
- **Resolution control** – Both paths respect the `detail_level` parameter, scaling output to `320 * detail_level` pixels on the longest axis.
- **Advanced processing** – The `generate_depth_map()` path adds gamma correction (power 1.5) and stronger Gaussian blur (5 × 5, σ = 1.5) for superior depth perception.
- **Modular design** – Depth generation remains decoupled from STL creation, with PNG persistence serving as the interchange format between stages.

## Frequently Asked Questions

### What determines whether the simple or advanced depth path is used?

The `skip_depth` boolean parameter in the `relief()` function controls the routing. When `skip_depth=False` (default), the system uses the simple built-in depth map creator. When `skip_depth=True`, the function delegates to `generate_depth_map()` for advanced processing.

### How does the `detail_level` parameter affect the depth map resolution?

Both generation paths calculate target dimensions using `320 * detail_level` as the base scaling factor. The simple path applies this directly to the image dimensions, while the advanced path uses it to set the longer side of the aspect-preserving resize, ensuring consistent pixel density regardless of input orientation.

### What mathematical transformations distinguish the advanced depth map generation?

The `generate_depth_map()` function applies gamma-like correction using `np.power(gray / 255.0, 1.5) * 255` after weighted luminance conversion (0.299R + 0.587G + 0.114B). It also employs a stronger 5 × 5 Gaussian blur compared to the 3 × 3 kernel used in the default path.

### How is the generated depth map passed to the STL creation stage?

The finalized 8-bit `uint8` array is first written to disk as a PNG file via `cv2.imwrite()`, then passed directly to `generate_stl()`. The STL generator interprets each pixel value as an extrusion height for the corresponding vertex in the 3D mesh.