Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/image-processing/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在Javascript中高效地迭代图像_Javascript_Image Processing_Canvas_Multidimensional Array_Web Worker - Fatal编程技术网

在Javascript中高效地迭代图像

在Javascript中高效地迭代图像,javascript,image-processing,canvas,multidimensional-array,web-worker,Javascript,Image Processing,Canvas,Multidimensional Array,Web Worker,我正在用JavaScript做一些图像处理项目,我需要迭代每个图像像素并进行一些其他处理以实现我的目标。 我正在使用画布获取图像像素数据数组。 对于小图像,如尺寸为500x300像素的图像,其工作良好,所需时间可接受。但对于尺寸为3000x3000像素的大型图像,迭代过程正在成为瓶颈,需要花费大量时间,比如10-12秒 那么,有没有什么方法或技巧可以用来减少迭代步骤中使用的时间呢 以下是我的想法:我尝试使用并行web workers(假设为4)来迭代图像数据的相等部分:(例如,0-[len/4]

我正在用JavaScript做一些图像处理项目,我需要迭代每个图像像素并进行一些其他处理以实现我的目标。
我正在使用画布获取图像像素数据数组。
对于小图像,如尺寸为500x300像素的图像,其工作良好,所需时间可接受。但对于尺寸为3000x3000像素的大型图像,迭代过程正在成为瓶颈,需要花费大量时间,比如10-12秒

那么,有没有什么方法或技巧可以用来减少迭代步骤中使用的时间呢

以下是我的想法:我尝试使用并行web workers(假设为4)来迭代图像数据的相等部分:(例如,
0-[len/4]
[len/4]+1-[len/2]
[len/2]+1-[len*3/4]
[len*3/4]+1-len
),其中
len
是图像数据数组的大小

我怀疑这种方法会更省时,因为Javascript是单线程的

 function rgb2grey(pix,offset){
        return (0.2989*pix[offset] + 0.5870*pix[offset+1] + 
    0.1140*pix[offset+2]);

}

function imgcompare(fileData1,fileData2,targetpix){
        var len = pix.length;
        for (var j = 0; j <len; j+=4) {
                var grey1 = rgb2grey(fileData1,j);
            var grey2 = rgb2grey(fileData2,j);
            if(grey1!=grey2){
                targetpix[j] = 255;
                targetpix[j+1] = targetpix[j+2] = 0;
            }
            else{
                targetpix[j] = fileData1[j];
                targetpix[j+1] = fileData1[j+1];
                targetpix[j+2] = fileData1[j+2];
            }       
            targetpix[j+3] = fileData1[j+3];
        }
}
功能rgb2grey(像素,偏移){
返回(0.2989*像素[偏移量]+0.5870*像素[偏移量+1]+
0.1140*pix[偏移量+2]);
}
函数imgcompare(fileData1、fileData2、targetpix){
var len=pix.length;
对于(var j=0;j)2D画布API和GPU辅助图像处理。
canvas 2D API提供了一组功能强大的GPU辅助合成操作。很多时候,它们可以替代通过Javascript完成的缓慢逐像素操作和通过getImageData读取像素

很多时候,这可以使处理成为视频或动画的实时解决方案,而且它还有一个优点,即它可以处理污染的画布,否则将无法使用任何其他方法

通过GPU辅助合成的OP处理 在问题示例中,使用canvas 2D composite操作有一定的优化空间。这将使用GPU为您进行每像素数学运算,但您必须创建两个额外的canvas

用红色标记两个图像之间不同的像素

  • 创建两个副本
  • 使用comp“difference”获取像素差异
  • 使用comp“饱和”产生不同的BW
  • 通过使用comp“lighter”在其自身上渲染差异来最大化差异
  • 使用comp difference反转差异,并在其上渲染白色矩形
  • 使用comp“Multiply”将imageA的副本与反向差相乘
  • 再次反转面具
  • 使用comp“multiply”将差异画布中的通道绿色和蓝色设置为零
  • 使用comp“lighter”将遮罩添加到原始遮罩图像
演示 演示加载两个图像,然后使用上述方法将两个图像之间的差异标记为红色(
“#F00”

//创建图像的副本作为画布
功能copyImage(图像){
const copy=document.createElement(“画布”);
copy.width=image.width;
copy.height=image.height;
copy.ctx=copy.getContext(“2d”);//为副本添加上下文以便于参考
copy.ctx.drawImage(图像,0,0);
返回副本;
}
//返回包含imageA和imageB之间差异的新画布
函数getDifference(imageA、imageB){
const dif=复制图像(imageA);
dif.ctx.globalCompositeOperation=“差异”;
dif.ctx.drawImage(imageB,0,0);
返回dif;
}
//将图像还原为黑白
函数makeBW(image){//color是有效的CSS颜色
image.ctx.globalCompositeOperation=“饱和”;
image.ctx.fillStyle=“#FFF”;
image.ctx.fillRect(0,0,image.width,image.height);
返回图像;
}
//如果超过值0,将所有通道设置为最大值(255)
函数MaxChannel(图像){
var i=8;//每次绘制时通道值加倍8倍,因此1*2^8得到255
image.ctx.globalCompositeOperation=“打火机”;
而(我--){
image.ctx.drawImage(图像,0,0)
}
返回图像;
}
//反转颜色通道resultRGB=255-imageRGB
函数反转(图像){
image.ctx.globalCompositeOperation=“差异”;
image.ctx.fillStyle=“#FFF”;
image.ctx.fillRect(0,0,image.width,image.height);
返回图像;
}
//保留遮罩中为白色的像素,如果遮罩中为黑色,则将像素设置为黑色。
函数maskOut(图像、掩码){
image.ctx.globalCompositeOperation=“乘法”;
image.ctx.drawImage(掩码,0,0);
返回图像;
}
//将通道从imageB添加到imageA。resultRGB=imageA_RGB+imageB_RGB
函数addChannels(imageA,imageB){//将imageB通道添加到imageA通道
imageA.ctx.globalCompositeOperation=“打火机”;
imageA.ctx.drawImage(imageB,0,0);
返回图像a;
}
//零通道是它的标志(红、绿、蓝)是真的
函数zeroChannels(图像、红色、绿色、蓝色){//将通道设置为零为真
image.ctx.fillStyle=`${red?'0:“F”}${green?'0:“F”}${blue?'0:“F”}`;
image.ctx.globalCompositeOperation=“乘法”;
image.ctx.fillRect(0,0,image.width,image.height);
返回图像;
}
//返回一个新画布,该画布是imageA的副本,其像素与标记为红色的imageB不同。
函数标记差异(imageA、imageB){
常量结果=复制图像(imageA);
const mask=invert(maxChannels(makeBW(getDifference(imageA,imageB)));
maskOut(结果、掩码);
返回addChannels(结果、零通道(反转(掩码)、false、true、true));
}
常量图像=[
"https://i.stack.imgur.com/ImeHB.jpg",
"https://i.stack.imgur.com/UrrnL.jpg"
];
var-imageCount=0;
函数onImageLoad(){
imageCount+=1;
如果(imageCount==2){
AddImagePage(标记差异(图像[0],图像[1]);
AddImagePage(图像[0]);
附加图像页(图像[1]);
}
}
函数AddImagePage(图像){
image.className=“images”;
document.body.appendChild(图像);
}
images.forEach((url,i)=>