Estimate depth from a single image

by Michael Prosser

HTML

<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs"></script>
<h1>Single Image Depth Estimation</h1>
  <input type="file" id="upload" accept="image/*" />
  <br />
  <canvas id="canvas"></canvas>

JavaScript

const MODEL_URL = 'https://huggingface.co/spaces/XciLai/Depth-Estimation-TFJS/resolve/main/model/model.json';

let model;

window.onload = async () => {
  model = await tf.loadGraphModel(MODEL_URL);
  console.log("Model loaded!");

  document.getElementById("upload").addEventListener("change", handleImageUpload);
};

async function handleImageUpload(event) {
  const file = event.target.files[0];
  const img = new Image();
  img.onload = async () => {
    const depthMap = await estimateDepth(img);
    drawDepthMap(depthMap);
  };
  img.src = URL.createObjectURL(file);
}

async function estimateDepth(img) {
  const inputTensor = tf.browser.fromPixels(img).resizeBilinear([256, 256]).toFloat().div(255.0);
  const batched = inputTensor.expandDims(0);

  const result = await model.executeAsync(batched);
  const depth = result.squeeze();  // shape: [256, 256]
  return depth;
}

function drawDepthMap(tensor) {
  const canvas = document.getElementById("canvas");
  const [height, width] = tensor.shape;
  canvas.width = width;
  canvas.height = height;

  // Normalize to 0-255 grayscale
  const normalized = tf.tidy(() => {
    const min = tensor.min();
    const max = tensor.max();
    return tensor.sub(min).div(max.sub(min)).mul(255).toInt();
  });

  tf.browser.toPixels(normalized, canvas).then(() => {
    normalized.dispose();
  });
}