first commit
This commit is contained in:
128
src/debug-failed.ts
Normal file
128
src/debug-failed.ts
Normal 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);
|
||||
Reference in New Issue
Block a user