first commit

This commit is contained in:
douboer
2025-10-25 15:53:29 +08:00
commit 7a4f659dda
321 changed files with 4588 additions and 0 deletions

128
src/debug-failed.ts Normal file
View File

@@ -0,0 +1,128 @@
import sharp from 'sharp';
import * as fs from 'fs';
import * as path from 'path';
async function debugSingle(imagePath: string) {
const basename = path.basename(imagePath);
console.log(`\n=== ${basename} ===`);
const { data, info } = await sharp(imagePath)
.raw()
.toBuffer({ resolveWithObject: true });
const { width, height, channels } = info;
const darkThreshold = 85;
const darkMap = new Uint8Array(width * height);
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const idx = (y * width + x) * channels;
const r = data[idx];
const g = data[idx + 1];
const b = data[idx + 2];
const brightness = (r * 0.299 + g * 0.587 + b * 0.114);
darkMap[y * width + x] = brightness < darkThreshold ? 1 : 0;
}
}
const visited = new Uint8Array(width * height);
const regions: Array<{x: number; y: number; w: number; h: number; pixels: number}> = [];
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const idx = y * width + x;
if (visited[idx] === 0 && darkMap[idx] === 1) {
let minX = x, minY = y, maxX = x, maxY = y, pixelCount = 0;
const stack: Array<[number, number]> = [[x, y]];
while (stack.length > 0) {
const [cx, cy] = stack.pop()!;
if (cx < 0 || cx >= width || cy < 0 || cy >= height) continue;
const cidx = cy * width + cx;
if (visited[cidx] === 1 || darkMap[cidx] !== 1) continue;
visited[cidx] = 1;
pixelCount++;
minX = Math.min(minX, cx);
minY = Math.min(minY, cy);
maxX = Math.max(maxX, cx);
maxY = Math.max(maxY, cy);
stack.push([cx + 1, cy], [cx - 1, cy], [cx, cy + 1], [cx, cy - 1]);
}
const w = maxX - minX + 1;
const h = maxY - minY + 1;
if (w >= 20 && h >= 20 && w < width * 0.9 && h < height * 0.9) {
regions.push({x: minX, y: minY, w, h, pixels: pixelCount});
}
}
}
}
console.log(`找到 ${regions.length} 个有效连通区域`);
// 过滤符合条件的候选
const candidates = regions.filter(r => {
const aspectRatio = r.w / r.h;
const density = r.pixels / (r.w * r.h);
const centerY = r.y + r.h / 2;
return (
r.w >= 50 && r.w <= 95 &&
r.h >= 50 && r.h <= 95 &&
aspectRatio >= 0.85 && aspectRatio <= 1.18 &&
centerY > height * 0.12 &&
centerY < height * 0.78 &&
density > 0.65
);
});
console.log(`符合严格条件的候选: ${candidates.length}`);
if (candidates.length > 0) {
candidates.forEach((r, i) => {
const aspectRatio = r.w / r.h;
const density = r.pixels / (r.w * r.h);
console.log(` ${i + 1}. [x=${r.x}, y=${r.y}, w=${r.w}, h=${r.h}] 宽高比=${aspectRatio.toFixed(2)}, 密度=${density.toFixed(2)}`);
});
} else {
// 尝试放宽条件
const relaxed = regions.filter(r => {
const aspectRatio = r.w / r.h;
const density = r.pixels / (r.w * r.h);
return (
r.w >= 45 && r.w <= 100 &&
r.h >= 45 && r.h <= 100 &&
aspectRatio >= 0.75 && aspectRatio <= 1.33 &&
r.y < height * 0.82 &&
r.y > height * 0.06 &&
density > 0.55
);
});
console.log(`符合放宽条件的候选: ${relaxed.length}`);
relaxed.slice(0, 5).forEach((r, i) => {
const aspectRatio = r.w / r.h;
const density = r.pixels / (r.w * r.h);
console.log(` ${i + 1}. [x=${r.x}, y=${r.y}, w=${r.w}, h=${r.h}] 宽高比=${aspectRatio.toFixed(2)}, 密度=${density.toFixed(2)}`);
});
}
}
async function main() {
const baseDir = path.join(__dirname, '..');
const doubanDir = path.join(baseDir, 'images', 'douban');
// 检查未检测到的图片
const failedFiles = ['滑块-2.png', '滑块-3.png', '滑块-6.png', '滑块-7.png', '滑块.png'];
for (const file of failedFiles) {
await debugSingle(path.join(doubanDir, file));
}
}
main().catch(console.error);