The captcha solver made by and for japanese high school girls!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

76 lines
2.9 KiB

export function connectedComponentLabeling(binaryImage: number[], width: number, height: number) {
const labels = Array(binaryImage.length).fill(0);
const linked: number[][] = [];
let nextLabel = 1;
function getNeighbors(row: number, col: number) {
const neighbors = [];
if (row > 0 && labels[(row - 1) * width + col] > 0) {
neighbors.push(labels[(row - 1) * width + col]);
}
if (col > 0 && labels[row * width + col - 1] > 0) {
neighbors.push(labels[row * width + col - 1]);
}
return neighbors;
}
// First pass
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
const idx = row * width + col;
if (binaryImage[idx] !== 0) {
const neighbors = getNeighbors(row, col);
if (neighbors.length === 0) {
linked[nextLabel] = [nextLabel];
labels[idx] = nextLabel;
nextLabel++;
} else {
neighbors.sort();
const smallestLabel = neighbors[0];
labels[idx] = smallestLabel;
for (let i = 1; i < neighbors.length; i++) {
linked[neighbors[i]] = linked[neighbors[i]].concat(linked[smallestLabel]);
linked[smallestLabel] = linked[smallestLabel].concat(linked[neighbors[i]]);
linked[neighbors[i]] = Array.from(new Set(linked[neighbors[i]]));
linked[smallestLabel] = Array.from(new Set(linked[smallestLabel]));
}
}
}
}
}
// Second pass
for (let idx = 0; idx < binaryImage.length; idx++) {
if (binaryImage[idx] !== 0) {
labels[idx] = Math.min(...linked[labels[idx]]);
}
}
return labels;
}
export function computeBounds(labels: number[], width: number, height: number) {
const bounds: Record<number, { minRow: number, minCol: number, maxRow: number, maxCol: number; area: number }> = {};
for (let row = 0; row < height; row++) {
for (let col = 0; col < width; col++) {
const idx = row * width + col;
const label = labels[idx];
if (label > 0) {
if (!bounds[label]) {
bounds[label] = { minRow: row, minCol: col, maxRow: row, maxCol: col, area: 1 };
} else {
if (row < bounds[label].minRow) bounds[label].minRow = row;
if (col < bounds[label].minCol) bounds[label].minCol = col;
if (row > bounds[label].maxRow) bounds[label].maxRow = row;
if (col > bounds[label].maxCol) bounds[label].maxCol = col;
++bounds[label].area;
}
}
}
}
return bounds;
}