簡體   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