Files
SlabUploader/frontend/src/mask/largestComponent.test.ts
T
grokbot_ty 0dd5d255ec fix(mask): keep only largest connected slab component
Sheet gaps after black/green removal left stray chunks in the bitset.
After keep predicates, zero all but the largest 4-connected component
and recompute slabPx before bbox / slabBounds.
2026-09-26 08:33:19 -07:00

69 lines
2.4 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { keepLargestComponent } from './largestComponent.ts';
test('keepLargestComponent: two blobs → only larger remains', () => {
// 10×6 grid: large 4×3 block (12 px) at left, small 2×2 (4 px) at right
const W = 10, H = 6;
const bitset = new Uint8Array(W * H);
for (let y = 1; y <= 3; y++)
for (let x = 1; x <= 4; x++) bitset[y * W + x] = 1;
for (let y = 2; y <= 3; y++)
for (let x = 7; x <= 8; x++) bitset[y * W + x] = 1;
const before = bitset.reduce((a, c) => a + c, 0);
assert.equal(before, 16);
const slabPx = keepLargestComponent(bitset, W, H);
assert.equal(slabPx, 12, 'slabPx is pixel count of largest blob');
// Large blob intact
for (let y = 1; y <= 3; y++)
for (let x = 1; x <= 4; x++)
assert.equal(bitset[y * W + x], 1, `large (${x},${y}) kept`);
// Small blob zeroed
for (let y = 2; y <= 3; y++)
for (let x = 7; x <= 8; x++)
assert.equal(bitset[y * W + x], 0, `small (${x},${y}) removed`);
assert.equal(bitset.reduce((a, c) => a + c, 0), 12);
});
test('keepLargestComponent: empty bitset → 0', () => {
const bitset = new Uint8Array(4 * 4);
assert.equal(keepLargestComponent(bitset, 4, 4), 0);
});
test('keepLargestComponent: single blob unchanged', () => {
const W = 5, H = 5;
const bitset = new Uint8Array(W * H);
for (let y = 1; y <= 3; y++)
for (let x = 1; x <= 3; x++) bitset[y * W + x] = 1;
const slabPx = keepLargestComponent(bitset, W, H);
assert.equal(slabPx, 9);
assert.equal(bitset.reduce((a, c) => a + c, 0), 9);
});
test('keepLargestComponent: 4-connected — diagonal touch is two components', () => {
// Two pixels only touching diagonally; larger is the two-pixel L on the left
// of a separate single pixel that is diagonal to nothing of equal size...
// Layout: three pixels as an L (size 3) and one diagonal fleck (size 1)
// . # .
// # # .
// . . #
const W = 3, H = 3;
const bitset = new Uint8Array(W * H);
bitset[0 * W + 1] = 1;
bitset[1 * W + 0] = 1;
bitset[1 * W + 1] = 1;
bitset[2 * W + 2] = 1; // diagonal-only to the L
const slabPx = keepLargestComponent(bitset, W, H);
assert.equal(slabPx, 3);
assert.equal(bitset[2 * W + 2], 0, 'diagonal fleck removed under 4-conn');
assert.equal(bitset[0 * W + 1], 1);
assert.equal(bitset[1 * W + 0], 1);
assert.equal(bitset[1 * W + 1], 1);
});