Canvas 黑块计数
使用图的连通分量算法计算 Canvas 中黑块的数量
问题
给定一个 Canvas,上面随机分布着一些黑块,计算 Canvas 上有多少个独立的黑块。
解答
这个问题可以转化为图的连通分量问题。基本思路是:先获取像素数据,然后使用深度优先搜索(DFS)或并查集来统计连通区域的数量。
实现步骤
- 使用
getImageData获取像素数组 - 创建一个
width * height的二维数组标记黑色像素 - 遍历所有像素,对每个未访问的黑色像素进行 DFS
function countBlackBlocks(canvas) {
const ctx = canvas.getContext('2d');
const width = canvas.width;
const height = canvas.height;
const imageData = ctx.getImageData(0, 0, width, height);
const pixels = imageData.data;
// 创建标记数组
const visited = Array.from({ length: height }, () => Array(width).fill(false));
const isBlack = Array.from({ length: height }, () => Array(width).fill(false));
// 标记黑色像素
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const index = (y * width + x) * 4;
const r = pixels[index];
const g = pixels[index + 1];
const b = pixels[index + 2];
// 判断是否为黑色(可根据实际情况调整阈值)
if (r < 50 && g < 50 && b < 50) {
isBlack[y][x] = true;
}
}
}
// DFS 遍历连通区域
function dfs(x, y) {
if (x < 0 || x >= width || y < 0 || y >= height) return;
if (visited[y][x] || !isBlack[y][x]) return;
visited[y][x] = true;
// 遍历四个方向
dfs(x + 1, y);
dfs(x - 1, y);
dfs(x, y + 1);
dfs(x, y - 1);
}
// 统计连通分量
let count = 0;
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
if (isBlack[y][x] && !visited[y][x]) {
dfs(x, y);
count++;
}
}
}
return count;
}
关键点
- 使用
getImageData获取像素数据,每个像素由 RGBA 四个值组成 - 将问题转化为图的连通分量问题,黑色像素作为节点,相邻黑色像素之间有边
- 使用 DFS 遍历每个连通区域,每次 DFS 完成代表找到一个独立黑块
- 也可以使用并查集算法实现,时间复杂度相同但代码更简洁
目录