tl;dr: Use an external library, like OpenCV, via FFI bindings. There are several ideas here on which functions to use and a lot of examples on how to use them on the OpenCV site.
... with NodeJS native approach and probably better solution than the ones listed on StackOverflow
Comparing images in a program is difficult. Let's take a simple, intuitive approach and compare pixels. If we compare pixels, both images need to have the same size. If they have the same pixels, they match. However, often, images look the same to the human eye, but differ ever so slightly, because they were processed by some optimization algorithm. Color values are different, there might be watermarks hidden, maybe someone added a slight noise or effect on top or stretched them. For a human, the pictures are still the same, or at least similar enough. What if someone re-scaled the picture? If we try to re-scale the picture ourselves, we will have to match the exact algorithm, or we might have pixels which do not match due to how the scaling was done.
As you can see, if we don't have the simplest case, we will run into trouble. However, what can we do in order to compare two images, which might have different scales and slightly different coloring?
I do not want to re-iterate the answers from the tl;dr above, so let me instead add another way to compare images.
0.0 to 1.0. Also save the dominant colors on all sides of the edge.This way, we remove the pixel comparison - we now compare shapes. There is no scale problem, because all edges are in a range of 0.0 to 1.0 in X and Y direction; you should allow for some deviation, though! Even the color problem is gone, because we only use defined dominant colors (red, green, blue, yellow, black, white), which are different enough. An edge could be stored in a struct like this:
const edge = {
coords: {
x: 0.01,
y: 0.782,
},
adjacentColors: {
up: Color.Red,
down: Color.White,
left: Color.Blue,
right: Color.Black,
},
};
You may define a max. deviation for the coords by for example 0.001, so the small differences through edge detection and scaling don't matter. If you transform another image into this format, you can do a 1:1 comparison per edge, and if they match, the images are visibly comparable.
The downside is, that edge detection is not necessarily reliable, and you might get positive results for similar, but visibly different images or negative results, if an image is blurry or warped. Also, JS was never made for big computations, so a native solution will be rather slow.
To get more accuracy, you should combine several methods in a weighted fashion - which means even more computations, which might even be quite expensive money-wise, depending on your project.