# One view, two shapes: a synthetic silhouette lab

An original, deliberately small counterexample for the Goblin3D article about input-aligned reconstruction. Two hand-authored 3D voxel shapes have exactly the same front silhouette and different side silhouettes. Matching one binary input view therefore does not uniquely determine hidden geometry.

**This is not a GenIA output, a reconstruction benchmark, an accuracy estimate, or a game-engine test.** No AI model or third-party asset was used. The numbers below describe only these two constructed shapes.

## Measured result

| View | A cells | B cells | Intersection | Union | IoU |
|---|---:|---:|---:|---:|---:|
| Front, parallel to y | 30 | 30 | 30 | 30 | 1.00 |
| Side, parallel to x | 18 | 30 | 18 | 30 | 0.60 |
| Top, parallel to z | 12 | 36 | 12 | 36 | 1/3 |

A contains 60 occupied unit cubes. B contains 108. The cap of A is 2 units deep; the cap of B is 8 units deep. Their front-view occupied cells are identical.

IoU is intersection size divided by union size. Both masks empty is explicitly defined as IoU 1; exactly one mask empty is IoU 0. Neither empty case occurs in the supplied fixture.

## Reproduce

Run these commands inside this directory with Python 3.10 or later:

```sh
python silhouette_lab.py
python -m unittest -v
```

Measurement and all 17 tests use only the Python standard library. To confirm there is no dependency on installed packages, the following also works:

```sh
python -S silhouette_lab.py
python -S -m unittest -v
```

To redraw the PNG, Pillow must already be available:

```sh
python silhouette_lab.py --render
```

The delivered render was generated with Pillow 12.3.0. Pillow only draws the measured cells; it does not compute silhouettes or IoU. The diagram uses installed DejaVu Sans fonts, with a default-font fallback. Its fixed display bounds are designed for the bundled fixture. Measurement itself preserves arbitrary integer positions, including negative ones.

## Method and coordinate convention

1. Expand the axis-aligned boxes in `synthetic-shapes.json` into occupied unit cubes. All minimum bounds are inclusive and maximum bounds exclusive; overlapping boxes contribute only one occupied cube per position.
2. Project by dropping the ray-axis coordinate: front maps `(x, y, z)` to `(x, z)`; side maps to `(y, z)`; top maps to `(x, y)`.
3. Deduplicate projected cells to produce exact binary occupancy masks. Compare the masks at the same world origin and scale, without camera fitting, translation, per-object cropping, or normalization.
4. Count intersection and union cells. Save counts, exact mask coordinates, IoUs, voxel totals, scope, and the fixture SHA-256 to `silhouette-report.json`.

Each image cell represents the orthographic projection of a unit cube. There is no perspective camera, antialiasing threshold, raster-image inference, lighting, shading, or material signal in this experiment. Camera rays run parallel to the named axis; ray direction along that axis does not alter a binary silhouette.

The source-view designation is conceptual: no input image was reconstructed. A and B were authored directly to exhibit the ambiguity. A second axis distinguishes this pair; it does not establish that two views always recover a unique 3D shape.

## Tests and inspection

`test_silhouette_lab.py` has 17 tests covering:

- Explicit expected coordinate mappings for all three camera axes
- Projection of an empty set and rejection of unknown views
- Both-empty, one-empty, disjoint, partial-overlap, and symmetric IoU cases
- Half-open box bounds, deduplication of overlapping boxes, negative coordinates, and invalid bounds
- Independent arithmetic for the two voxel totals
- Exact front and side expected masks authored directly in 2D
- All reported counts and IoUs, plus exact reproducibility of the saved JSON

The expected masks and numbers are independent assertions, rather than values copied from the projection output at runtime. `test-results.txt` records the delivered successful test run. The PNG was also opened and visually checked.

## Files

- `silhouette_lab.py`: measurement implementation and optional Pillow renderer
- `synthetic-shapes.json`: original, human-readable box fixtures and provenance
- `test_silhouette_lab.py`: unit tests
- `silhouette-report.json`: machine-readable measurement report, including exact masks
- `silhouette-ambiguity.png`: 1800 × 1170 explanatory figure
- `test-results.txt`: successful run log
- `silhouette-lab.zip`: downloadable copy of the seven files above, including this README

## Suggested figure text

Alt text: Two synthetic voxel props share an identical 30-cell front silhouette, with front IoU 1.00. From the side, the deeper cap adds 12 projected cells, producing an 18-cell intersection and 30-cell union, or side IoU 0.60.

Caption: Original synthetic counterexample: a perfect binary front-silhouette match can coexist with different hidden depth. These are constructed voxel shapes, not GenIA reconstructions or game-ready assets.

## Interpretation limit

This example supports only a geometric non-uniqueness claim for a single binary orthographic silhouette. It does not measure GenIA or another system, predict real reconstruction quality, compare algorithms, or establish anything about topology, UVs, materials, collision, retopology, or engine readiness. Richer input cues and learned priors can constrain reconstruction beyond the silhouette considered here.
