繁体   English   中英

Javascript画布:如何有效地计算两幅画布的距离

[英]Javascript canvas: how to efficiently compute distance of two canvases

我想计算两个画布中绘制的两个数字之间的距离,实际上我正在做以下操作,迭代画布的数据(画布具有相同的大小):

var computeDifference = function() {

    var imgd1 = bufferCtx.getImageData(0, 0, w, h).data;
    var imgd2 = targetCtx.getImageData(0, 0, w, h).data;

    var diff = 0;

    for(var i=0; i<imgd1.length; i+=4) {
        var d = (imgd1[i]-imgd2[i]);
        var tot = d > 0 ? d : -d;
        diff += tot
    }

    return diff;
}

这不是很有效率。

有更好的方法吗? 我读到了关于复合操作的内容,但我不确定在这种情况下这是否有帮助。

我故意只考虑R频道,因为现在我正在使用黑白图像,但我可能会考虑其他频道。

您可以在单个画布上使用新的difference 混合方法,在最后一次绘制之前使用模式设置绘制两个图像,然后提取位图数据以获得总和。

您可以使用相同的属性globalCompositeOperation来设置混合模式。

这样您就可以让浏览器完成初始工作,计算每个组件的差异,只留下它们。 您还要保存一个画布,一个调用getImageData() ,这在硬件加速系统上相对昂贵:

ctx.drawImage(image1, x, y);
ctx.globalCompositeOperation = "difference";  // use composite to set blending...
ctx.drawImage(image2, x, y);

// extract data, and sum -

注意:IE11不支持新的混合模式。 对于IE,您需要手动进行差异计算。

您可以通过在支持时提供快速方法,在不提供时手动检测此功能:

ctx.globalCompositeOperation = "difference";
if (ctx.globalCompositeOperation === "difference") {
    // fast
}
else {
    // manual
}

现场表演测试

Test1将做手动差异校准,test2将使用浏览器差异混合模式。 在我的设置中,FireFox赢得超过4倍的因素 (Chrome中的差异略小)。

 var canvas1 = document.createElement("canvas"), canvas2 = document.createElement("canvas"), ctx1 = canvas1.getContext("2d"), ctx2 = canvas2.getContext("2d"), img1 = new Image, img2 = new Image, count = 2, startTime1, startTime2, endTime1, endTime2, sum1, sum2; performance = performance || Date; // "polyfill" the performance object img1.crossOrigin = img2.crossOrigin = ""; // we need to extract pixels img1.onload = img2.onload = loader; img1.src = "http://i.imgur.com/TJiD5GM.jpg"; img2.src = "http://i.imgur.com/s9ksOb1.jpg"; function loader() {if(!--count) test1()} // handle async load function test1(){ startTime1 = performance.now(); ctx1.drawImage(img1, 0, 0); ctx2.drawImage(img2, 0, 0); var data1 = ctx1.getImageData(0, 0, 500, 500).data, data2 = ctx2.getImageData(0, 0, 500, 500).data, i = 0, len = data1.length, sum = 0; // we do all channels except alpha channel (not used in difference calcs.) while(i < len) { sum += Math.abs(data2[i] - data1[i++]) + Math.abs(data2[i] - data1[i++]) + Math.abs(data2[i] - data1[i++]); i++ } sum1 = sum; endTime1 = performance.now(); test2(); } function test2(){ startTime2 = performance.now(); ctx1.drawImage(img1, 0, 0); ctx1.globalCompositeOperation = "difference"; if (ctx1.globalCompositeOperation !== "difference") alert("Sorry, use Firefox or Chrome"); ctx1.drawImage(img2, 0, 0); var data = ctx1.getImageData(0, 0, 500, 500).data, i = 0, len = data.length, sum = 0; // we do all channels except alpha channel while(i < len) { sum += data[i++]; sum += data[i++]; sum += data[i++]; i++; } sum2 = sum; endTime2 = performance.now(); result(); } function result() { var time1 = endTime1 - startTime1, time2 = endTime2 - startTime2, factor = time1 / time2, res = "Manual method: " + time1.toFixed(3) + "ms<br>"; res += "Blending mode: " + time2.toFixed(3) + "ms<br>"; res += "Factor: " + factor.toFixed(2) + "x<br>"; res += "Sum 1 = " + sum1; res += "<br>Sum 2 = " + sum2; document.querySelector("output").innerHTML = res; } 
 <output>Loading images and calculating...</output> 

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM