Sean Sean - 15 days ago 6
Javascript Question

Are there any javascript libs to pixel compare images using HTML5 canvas (or any other means)?

Would like to test if 2 images pixel match and/or whether a smaller sized image pixel matches some same sized section of a larger image.

Answer

The first part, test if two images match perfectly, is pretty straight forward.

//assuming data1,data2 are canvas data of images of the same size
function isMatch(data1,data2){
    for(var i = 0; i<data1.length; i++){
        if(data1[i] != data2[i]) return false;
    }
    return true;
}

As long as you aren't using extremely hi-res images I wouldn't worry about speed, one iteration trough canvas data like this is typically very fast, ~10ms per Mega Pixel on a decent computer with a modern browser. Remember width and height of the images must be the same. For most practical purposes this yes or no match is not very useful, encoding errors lead to imperceptible changes in images, it is best to use a metric to measure how far apart the two images are. A naive but fairly effective metric is the RMS of the two images:

//assuming data1,data2 are canvas data of images of the same size
function rmsDiff(data1,data2){
    var squares = 0;
    for(var i = 0; i<data1.length; i++){
        squares += (data1[i]-data2[i])*(data1[i]-data2[i]);
    }
    var rms = Math.sqrt(squares/data1.length);
    return rms;
}

Here the rms will range from [0,255], 0 if the images match exactly, 255 if one image is all rgba(0,0,0,0) and the other is all rgba(255,255,255,255). How to threshold what is an acceptable rms difference is up to you to tune (around 1 to 2 perhaps).

For the second part of your question, whether a smaller sized image pixel matches some same sized section of a larger image, I'm assuming that they are not translated and that we know the scale difference between the two, otherwise this would open it up into a very complicated and interesting problem see Pattern Recognition. Then with this egregious assumption I would use the canvas to scale the large image down to the exact same size as the smaller one and get the rms between them. Don't test for an exact match as scaling will always create slight errors and never be an exact match.

Comments