本文介绍利用 HTML5 Canvas 的 getImageData 方法获取图片像素 RGBA 数据,通过遍历判断透明度通道(Alpha)是否为 0 来识别有效点。结合递归算法处理上下左右相邻点的连通性,并将已处理的点数据置零以避免重复计数,最终统计出图片中非透明点的总数。该方法适用于 PNG 格式图片的点状目标计数场景。
前言与实现思路
前言
图像由连续的像素点数据构成,每个像素包含四个通道的长度信息,即红、绿、蓝和透明度(RGBA)。通过遍历这些像素数据并配合特定的处理逻辑,可以实现对图像中特定像素点数量的统计与判断。

实现思路
本示例使用 PNG 格式图片,核心判断依据是像素的透明度(Alpha 通道)是否为零。若某点透明度不为零,则判定其为有效点(如小球上的点);接着检查其上下左右相邻点的透明度,若不为零则递归处理,并将当前点的 RGBA 信息置为零。主循环结束后进行计数,直至遍历完成。
具体步骤与代码实现
具体步骤
首先创建 Canvas 对象并获取绘图上下文,加载目标图片。使用 Canvas 的 drawImage 方法将图片绘制到画布上,参数包括图片对象、贴图起点的横纵坐标以及贴图的宽度和高度。
var canvas = document.createElement('canvas'),
var ctx = canvas.getContext('2d');
ctx.drawImage(imgObj, 0, 0,imgWidth,imgHeight);
利用 Canvas 的 getImageData 方法获取图片的像素数据,该方法返回包含各点 RGBA 信息的对象。参数包括采样区域的起始横坐标、起始纵坐标、宽度及高度。
var imageData = ctx.getImageData(0,0,width,height);
//改写imageData.data信息实现点的计数
遍历 imageData.data 数组,该数组每四个元素代表一个像素的 RGBA 值,因此循环步长为 4。当检测到某点透明度(Alpha)不为零时,调用处理函数并终止当前递归分支(防止因短时间内过多循环导致内存溢出)。主循环条件为 numberStart 小于 imageData.data.length 减 1,number 记录最终点的数量,numberStart 记录上次循环结束时的索引值,judgeZero 为处理函数。
function repeateData(){
for(var i=numberStart;i<imageData.data.length;i+=4){
numberStart+=4;
var a = imageData.data[i+3];
if(a != 0) {
judgeZero(i,number);
break;
}
}
if(numberStart<imageData.data.length-1){
repeateData()
}else{
console.log(number);
}
}
点的处理函数根据图片宽高计算当前点的坐标 (x, y),并据此计算出该点上下左右四个相邻点的透明度信息。
function judgeZero(index){
number++;
clearPoints(index);
}
function clearPoints(index){
var x = (index/4)%width,
y = Math.floor(index/4/width);
var up = (x+(y-1)*width)*4,
down = (x+(y+1)*width)*4,
right = (x+1+y*width)*4,
left = (x-1+y*width)*4;
var uA = imageData.data[up+3],
bA = imageData.data[down+3],
rA = imageData.data[right+3],
lA = imageData.data[left+3];
}
function clearRgb(index){
imageData.data[index] = 0;
imageData.data[index+1] = 0;
imageData.data[index+2] = 0;
imageData.data[index+3] = 0;
}
判断四个方向的透明度是否为零。若不为零,则继续调用处理函数,并擦除该点信息,确保该点不再被重复计数。
if(uA != 0){
clearRgb(up);
clearPoints(up);
}
if(bA != 0){
clearRgb(down);
clearPoints(down);
}
if(rA != 0){
clearRgb(right);
clearPoints(right);
}
if(lA != 0){
clearRgb(left);
clearPoints(left);
}
将所有透明度不为零的有效点信息置为零,使得这些点在后续的主循环判断中不再产生影响。
function clearRgb(index){
imageData.data[index] = 0;
imageData.data[index+1] = 0;
imageData.data[index+2] = 0;
imageData.data[index+3] = 0;
}
执行4,5,6步骤直至所有点rgba信息都被置为0,主循环继续,最后可得到数量。
总结
总结
主要原理是获取图像中一个有效点,通过上下左右递归判断连续点并消除其信息,当该点及其连通区域在 imageData.data 中全部被抹去时,记为一个点。主循环继续处理剩余点。图片需为 PNG 格式,点的形状不限于圆形。该方法仅供参考。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持本站。