# The Score That Lies

*Task 2 of 5 · [Template Matching](https://gpu.rocks/learn/template-matching-f57b4bed.md) · GPU.js Learn*

Now break it. `brightScene` is the same scene photographed in brighter
light: every value 0.28 higher, nothing moved, nothing changed shape. The patch is still
exactly where it was. Run the same kernel over it — the kernel is not what is wrong here —
and the best match walks off to a completely different place.

Here is why, in one line of algebra. Add δ to every scene value and the score at a
window becomes

```js
SSD(w + δ, t) = SSD(w, t)
              + 2δ · sum(wᵢ − tᵢ)
              + n · δ²
```

At the true match the pixels agree, so `sum(wᵢ − tᵢ)` is zero and there is
nothing to offset the last term: a *perfect* match now scores
`64 × 0.28² = 5.02`. Meanwhile any window that is **darker** than
the template has a negative `sum(wᵢ − tᵢ)`, and the middle term pays it a
discount. Somewhere in this scene sits a patch that is dark and matches badly; brighten
the picture and its discount beats a perfect match outright.

That is the whole lesson of this module, and it is not really about vision. SSD is not
a measure of similarity — it is a measure of **distance in absolute value**,
and every camera, every light, every exposure, every gain setting moves absolute values
around. A score that cannot tell "brighter" from "different" will confidently point at
the wrong thing.

## Figures

- **the same two windows, before and after somebody turned the lights up**

## Goal

**Goal:** score both scenes with the same SSD kernel and show the damage
— log where each one thinks the patch is, and the two bright-scene scores that explain it.

## Requirements

- Score `scene` and `brightScene` with the same kernel
- `console.log` the best position on each map — they disagree
- From the bright map, `console.log` the score at the true position and the score the winner got — the winner's is smaller

## Hint 1 — nothing about the kernel changes

Same kernel, called twice. `brightScene` has exactly the same shape
as `scene`, so the second call costs you one line.

## Hint 2 — reading a known cell

The map is indexed `map[y][x]`, so the score the bright map gives
the true position is `brightMap[TRUE_Y][TRUE_X]`. Compare it against
`bestMatch(brightMap).score`.

## Same idea elsewhere

Every practitioner meets this wall. It is why OpenCV ships
`TM_CCOEFF_NORMED` alongside `TM_SQDIFF`, why stereo matchers use
census transforms or rank filters instead of raw differences, and why "we normalised the
inputs and the model started working" is the most common debugging story in machine
learning. A raw difference is a distance in whatever units the sensor happened to
produce.

## Starter code

```js
// Same kernel, two scenes. The kernel is not what is wrong here.
const gpu = new GPU({ mode });

const ssd = gpu.createKernel(function (scene, patch) {
  const x = this.thread.x;
  const y = this.thread.y;
  let sum = 0;
  for (let j = 0; j < this.constants.size; j++) {
    for (let i = 0; i < this.constants.size; i++) {
      const d = scene[y + j][x + i] - patch[j][i];
      sum += d * d;
    }
  }
  return sum;
}, {
  output: [89, 89],
  constants: { size: 8 },
});

function bestMatch(map) {
  let best = Infinity;
  let bx = 0;
  let by = 0;
  for (let y = 0; y < map.length; y++) {
    for (let x = 0; x < map[y].length; x++) {
      if (map[y][x] < best) {
        best = map[y][x];
        bx = x;
        by = y;
      }
    }
  }
  return { x: bx, y: by, score: best };
}

// Where the patch really is — task 1 found it.
const TRUE_X = 58;
const TRUE_Y = 21;

const plainMap = await ssd(scene, patch);
const brightMap = await ssd(brightScene, patch);

// TODO: log the best position on each map.
// TODO: log brightMap's score at the true position, and the score its winner
//       got. The winner's is smaller — that is the failure, in two numbers.
```

---

Interactive version: https://gpu.rocks/learn/template-matching-f57b4bed/2

[Previous task](https://gpu.rocks/learn/template-matching-f57b4bed/1.md) · [Next task](https://gpu.rocks/learn/template-matching-f57b4bed/3.md)
