← All work
Archive · 2023  Write-up

Browser vision models

Two computer vision models exported to TensorFlow.js and wrapped in plain web pages: one sorts brain scans into four dementia-stage labels, the other labels every region of a street photo. Both run on your device, so images never get uploaded anywhere.

2
models, no server
~90%
classifier average in project testing
31
street-scene classes
128×128
segmentation map per image
Role · Solo Stack · TensorFlow.js · JavaScript · HTML canvas
Built
Nov 1–4, 2023
Repos
2
Commits
108 in 2023, 2 README updates
Weights
9 shards4 + 5, loaded by the browser
01 · Timeline

One week in November 2023

  1. Nov 1, 2023
    Street-scene segmentation

    Uploaded the exported graph model (a manifest plus five weight shards), the class list, and a page that runs it on a photo and paints the result onto a canvas.

    GitHub5 commits5e2db90 ↗
  2. Nov 4, 2023
    Brain-scan classifier

    Same approach with a four-class classification model in four shards, an upload button, and a sample image to try it on.

    GitHub3 commits3aa9486 ↗
  3. Jun 13, 2026
    Documented properly

    Rewrote both READMEs with model summaries, how I verified the files, and clear limitations.

02 · The classifier

Four labels, and one of them is much weaker

The classifier takes a brain scan at whatever size you give it and returns scores for four labels: non-demented, very mild, mild, and moderate. The page loads the model, turns the image into a tensor, and shows the top label.

index.html
async function predict() {
  const model = await tf.loadGraphModel('./model.json');
  let example = tf.browser.fromPixels(document.getElementById("img1"), 3).cast('float32');
  example = example.reshape([1, ...example.shape]);
  const scores = await model.predict(example).data();
  const classes = ["MildDemented", "ModerateDemented", "NonDemented", "VeryMildDemented"];
  result.innerHTML = classes[scores.indexOf(Math.max(...scores))];
}

Tidied from index.html.

ClassPrecision in project testing
ModerateDemented100.00%
VeryMildDemented97.93%
MildDemented94.40%
NonDemented65%

The average was around 90%, but non-demented scans were the weakest class by a wide margin.

Low precision on the healthy class is the number to worry about. It means the model often called a scan non-demented when it wasn't, which is the worst kind of mistake for this task. It's a learning prototype and nothing like a clinical tool, and the repo doesn't include the training data or an independent validation set.

03 · The segmenter

A label for every pixel block

The segmentation model takes a 256×256 street photo and outputs a 128×128 grid with a score for each of 31 classes in every cell: road, sidewalk, car, pedestrian, bicyclist, traffic light, building, tree, sky, and so on. The page takes the highest-scoring class per cell and colors it on a canvas.

For colors I used a cheap trick: each class id goes through a little modular formula ((32 + id × 754) mod 256 for red, with different constants for green and blue). Every class gets a stable color without a hand-built palette. The downside is there's no legend yet, so you can't tell which color is which without the class list.

04 · What's missing

What these would need to be more than demos

Both run from a static file server.

Clone either repo and run python -m http.server.

More work