# AI depth for photos Choose a photo, then select **AI 깊이 생성**. The app snapshots the decoded photo, sends the snapshot to a module worker, and runs Depth Anything V2 Small through Transformers.js. WebGPU is tried first; the worker retries with WASM if WebGPU is unavailable or fails. The first run downloads the model files from Hugging Face. Inference itself runs in the browser, and the photo pixels are not sent to the model host. For the 2026-10-06 comparison, **개발 비교 → AI 깊이 모델** can select V2 Base, then **AI 깊이 생성** recomputes the same photo at input 770. Small remains the default; Base is a noncommercial test option. Switching the model keeps the current depth until inference succeeds and does not change zoom, pan, glass settings or photo–glass distance. Only one estimator is kept in the worker at a time. The same-photo Small/Base values, maximum masks and distance checks are recorded in [the Base QA report](qa-ai-depth-base-2026-10-06/report.md). Both models' maxima were in the nose region; Base did not establish a dramatic improvement of facial geometry. **최대 깊이 영역 확인** overlays the normalized Float32 maximum (`1`, pink), byte-texture maximum (`255/255`, cyan), and near-maximum (`≥0.99`, yellow) on the original photo. Counts and the first maximum's image coordinates are displayed. Clicking the preview or entering pixel coordinates shows both normalized model and byte-rendering values. The Float32 map is retained solely for inspection; the geometry still uses the existing byte texture and 128×128 mesh. A normalized maximum is guaranteed for any nonconstant finite prediction and is not evidence of correct anatomical depth. Byte rounding can create a larger `depth=1` area. Distance stays anchored to the **whole-map maximum**, without a semantic nose detector: `gap(pixel) = photoGlassGap + (maxDepth - byteDepth(pixel)) * depthScale`. The diagnostic gap is the map-point value in scene units, not cm or an exact measure of the interpolated mesh triangle. The maximum surface's gap is 0.04–0.60. Other points retain their depth differences and the RGB/Depth transform and refraction base plane move together. The source image is resized proportionally so its longest edge is at most 1024 pixels. Transformers.js preserves the image aspect ratio when preparing its model input and resizes the prediction to that same snapshot. The relative depth output is normalized per image to grayscale bytes: **0 is far/back and 255 is near/front**. The shader samples those bytes as normalized red-channel values from 0 to 1. Depth Anything V2 predicts relative inverse depth, so larger raw prediction values map to nearer points. This is an estimate, not measured distance or a complete 3D reconstruction. As of 2026-10-06, the processor's nominal input size is **770**, configured by `AI_DEPTH.inputSize` in `src/constants/depth.ts`. The shared estimator loader applies it to both WebGPU and WASM. Aspect ratio and alignment to multiples of 14 still determine the actual tensor dimensions; the final map remains the snapshot's size. The UI displays `입력 770`. Browser verification and the 518 comparison are recorded in [the 770 QA report](qa-ai-depth-770-2026-10-06/report.md). AI depth can be generated for still photos only. While the photo is changing, a manual depth map is loading, or inference is running, the button is disabled. A source change cancels the worker request. A successful result replaces the active depth and switches to **Final**; choose **No Glass** for parallax review. A failure leaves the current depth in place and the button can be used to retry. ## Model and license - Model: [`onnx-community/depth-anything-v2-small-ONNX`](https://huggingface.co/onnx-community/depth-anything-v2-small-ONNX), Apache-2.0. - Optional test model: [`onnx-community/depth-anything-v2-base-ONNX`](https://huggingface.co/onnx-community/depth-anything-v2-base-ONNX), CC-BY-NC-4.0. - Runtime: [`@huggingface/transformers` 4.3.0](https://github.com/huggingface/transformers.js), Apache-2.0. - The model follows [Depth Anything V2](https://github.com/DepthAnything/Depth-Anything-V2); the Small model is distributed under Apache-2.0 in the upstream project. The AI depth provenance label names the model. The deployed [third-party notice](../public/THIRD-PARTY-NOTICES.txt) and [Apache 2.0 license text](../public/licenses/Apache-2.0.txt) are copied into `dist/` by Vite. Model weights are cached by the browser runtime when available. ## Browser smoke test Start the app on a local URL, then run `npm run ai-depth-smoke`. The script loads the supplied sample, performs real model inference, records the normalized worker result at the sample's nose, eye, face, ear, and body landmarks, captures No Glass before and after a drag, captures Final after the drag, checks 390-pixel horizontal overflow, captures a mobile screenshot, and switches photos during a second request to check stale-result cancellation. It records browser console/page/request errors alongside the results. Set `AI_DEPTH_BASE_URL` if Vite is running on a different local address. Set `CHROME_EXECUTABLE_PATH` or `PLAYWRIGHT_CHROMIUM_PATH` when using a specific installed Chrome/Chromium executable; without either variable, Playwright's default executable is used. The script does not hard-code a machine-specific browser path. Output is written to `test-results/ai-depth/`. ## Validation On 2026-09-14, headless Chrome with WebGPU completed first-use model download and inference in 11.1 seconds. No Glass showed a recognizable dog face; Final Mosaic and Reeded/Frosted rendered without page errors. The captured normalized landmark depths were nose 0.722, left eye 0.694, right eye 0.651, ears 0.667/0.596, and body 0.671. These facial/object differences are subtle compared with the deliberately exaggerated hand-authored test map. The 390-pixel layout had no horizontal overflow, manual depth input remained usable, and switching photos during a second request prevented the stale AI result from applying. The browser console still reported ONNX CPU-assignment warnings and the existing missing-favicon 404; the page-error count was zero. Actual video playback, WASM-only runtime, and inference performance on a physical mobile device were not measured.