JavaScript实现2D像素数组全同色矩形坐标查找方案
二维数组多色矩形识别实现
原代码核心问题
- 所有像素判断逻辑硬编码了目标值为
1,完全无法识别其他颜色值的矩形 - 标记已识别区域时直接将像素值改为
2,会覆盖数组内原本的2号颜色像素,干扰后续识别流程 - 识别结果未关联对应颜色值,无法匹配多色矩形的分组输出要求
核心改造逻辑
- 扫描左上角起点时,不再固定查找值为1的像素,而是定位第一个非0(即已填充)的像素,记录该像素的颜色值作为当前矩形的匹配标准
- 矩形右边界校验、列方向下边界推导全部使用记录的目标颜色值,不再依赖硬编码固定值
- 标记已识别区域时,将对应位置的像素值改为
0(空白值),彻底避免和实际1-10的颜色值冲突 - 每个识别出的矩形对象新增
color字段,记录对应的颜色属性,方便按要求分组输出
可直接运行的完整代码
// 注意:原数组会在识别过程中被临时修改为0标记已识别区域,如需保留原数组可先做深拷贝 const grid = [ [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //y=0 [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 4, 4], //y=1 [1, 1, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0], //y=2 [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 0, 0, 0, 0, 0, 0], //y=3 [1, 1, 1, 3, 3, 3, 3, 3, 0, 0, 2, 2, 2, 2, 2, 2], //y=4 [1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 2, 2, 2, 2, 2, 2], //y=5 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 2, 2], //y=6 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //y=7 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //y=8 [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //y=9 [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 1, 1, 1, 2, 2, 2], //y=10 [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //y=11 [0, 2, 2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], //y=12 [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //y=13 [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0], //y=14 [0, 2, 2, 2, 2, 2, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0] //y=15 ]; const WIDTH = grid[0].length; const HEIGHT = grid.length; // 计算所有已填充像素的总面积 let totalFilledArea = 0; for (let y = 0; y < HEIGHT; y++) { for (let x = 0; x < WIDTH; x++) { totalFilledArea += grid[y][x] > 0 ? 1 : 0; } } const detectedRects = []; let processedArea = 0; // 循环识别直到所有已填充像素都被标记处理 while (processedArea < totalFilledArea) { const currentRect = findNextValidRect(); detectedRects.push(currentRect); markRectAsProcessed(currentRect); processedArea += (currentRect.x2 - currentRect.x1 + 1) * (currentRect.y2 - currentRect.y1 + 1); } // 按颜色分组输出,和期望格式对齐 const rectsByColor = detectedRects.reduce((acc, rect) => { const c = rect.color; if (!acc[c]) acc[c] = []; acc[c].push(rect); return acc; }, {}); console.log('识别结果:', rectsByColor); function findNextValidRect() { let startFound = false; const rect = { x1: 0, x2: WIDTH - 1, y1: 0, y2: HEIGHT - 1, color: 0 }; // 查找矩形左上角起点 for (let x = 0; x < WIDTH; x++) { for (let y = 0; y < HEIGHT; y++) { if (grid[y][x] > 0) { rect.x1 = x; rect.y1 = y; rect.color = grid[y][x]; // 记录当前矩形的目标颜色 startFound = true; break; } } if (startFound) break; } // 推导矩形右边界和下边界 for (let x = rect.x1; x <= rect.x2; x++) { // 同一行当前位置颜色不匹配,截断右边界 if (grid[rect.y1][x] !== rect.color) { rect.x2 = x - 1; break; } // 逐列向下校验颜色,遇到不匹配则截断下边界 for (let y = rect.y1; y <= rect.y2; y++) { if (grid[y][x] !== rect.color) { rect.y2 = y - 1; break; } } } return rect; } // 标记已识别区域为0(空白),避免重复识别 function markRectAsProcessed({ x1, y1, x2, y2 }) { for (let x = x1; x <= x2; x++) { for (let y = y1; y <= y2; y++) { grid[y][x] = 0; } } }
运行结果说明
代码运行后输出的按颜色分组的矩形列表,完全匹配给出的坐标样例:
- 颜色1对应的5个矩形坐标和样例中的绿色矩形完全一致(修正了样例中第五个矩形
y1:15的笔误,实际为y2:15) - 颜色2对应的4个矩形坐标和样例中的红色矩形完全一致
- 颜色3、4对应的单矩形坐标也和样例匹配
内容的提问来源于stack exchange,提问作者The Sycorax
相关产品推荐
相关产品推荐

