One method that may help, due to how long this library has been around and how well it seems to be maintained is to use ImageMagick. Let me demonstrate.
1 install the Pod using
pod 'ImageMagick', '6.8.8-9'
2 in the viewController or whatever other view you want to do your comparisons between images, import the following:
#import <wand/MagickWand.h>
4 create easy mode exception "Macro" to check for errors without having to code up the exception method every time you need to check for exceptions:
#define ThrowWandException(wand) { \
char * description; \
ExceptionType severity; \
\
description = MagickGetException(wand,&severity); \
(void) fprintf(stderr, "%s %s %lu %s\n", GetMagickModule(), description); \
description = (char *) MagickRelinquishMemory(description); \
exit(-1); \
}
3 create comparison method to compare two images:
-(void)compareTwoImages:(UIImage*)firstImage secondImage:(UIImage*)secondImage comparitorSize:(size_t)comparitorSize {
double diff1, diff2, diff3, diff4, diff5, diff6, diff7, diff8, diff9, diff10, diff11, diff12;
MagickWandGenesis();
MagickWand *magick_wand_1 = NewMagickWand();
NSData * dataObject1 = UIImagePNGRepresentation(firstImage);
MagickBooleanType status1;
status1 = MagickReadImageBlob(magick_wand_1, [dataObject1 bytes], [dataObject1 length]);
if (status1 == MagickFalse) {
ThrowWandException(magick_wand_1);
}
MagickWandGenesis();
MagickWand *magick_wand_2 = NewMagickWand();
NSData * dataObject11 = UIImagePNGRepresentation(secondImage);
MagickBooleanType status11;
status11 = MagickReadImageBlob(magick_wand_2, [dataObject11 bytes], [dataObject11 length]);
if (status11 == MagickFalse) {
ThrowWandException(magick_wand_2);
}
MagickScaleImage(magick_wand_2, comparitorSize, comparitorSize);
MagickScaleImage(magick_wand_1, comparitorSize, comparitorSize);
MagickWandGenesis();
MagickWand *magick_wand_3 = NewMagickWand();
MagickCompareImages(magick_wand_1, magick_wand_2, UndefinedMetric, &diff1);
MagickCompareImages(magick_wand_1, magick_wand_2, AbsoluteErrorMetric, &diff2);
MagickCompareImages(magick_wand_1, magick_wand_2, MeanAbsoluteErrorMetric, &diff3);
MagickCompareImages(magick_wand_1, magick_wand_2, MeanErrorPerPixelMetric, &diff4);
MagickCompareImages(magick_wand_1, magick_wand_2, MeanSquaredErrorMetric, &diff5);
MagickCompareImages(magick_wand_1, magick_wand_2, PeakAbsoluteErrorMetric, &diff6);
MagickCompareImages(magick_wand_1, magick_wand_2, PeakSignalToNoiseRatioMetric, &diff7);
MagickCompareImages(magick_wand_1, magick_wand_2, RootMeanSquaredErrorMetric, &diff8);
MagickCompareImages(magick_wand_1, magick_wand_2, NormalizedCrossCorrelationErrorMetric, &diff8);
MagickCompareImages(magick_wand_1, magick_wand_2, FuzzErrorMetric, &diff10);
MagickCompareImages(magick_wand_1, magick_wand_2, UndefinedErrorMetric, &diff11);
MagickCompareImages(magick_wand_1, magick_wand_2, PerceptualHashErrorMetric, &diff12);
NSLog(@"UndefinedMetric: %.21f", diff1);
NSLog(@"AbsoluteErrorMetric: %.21f", diff2);
NSLog(@"MeanAbsoluteErrorMetric: %.21f", diff3);
NSLog(@"MeanErrorPerPixelMetric: %.21f", diff4);
NSLog(@"MeanSquaredErrorMetric: %.21f", diff5);
NSLog(@"PeakAbsoluteErrorMetric: %.21f", diff6);
NSLog(@"PeakSignalToNoiseRatioMetric: %.21f", diff7);
NSLog(@"RootMeanSquaredErrorMetric: %.21f", diff8);
NSLog(@"NormalizedCrossCorrelationErrorMetric: %.21f", diff9);
NSLog(@"FuzzErrorMetric: %.21f", diff10);
NSLog(@"UndefinedErrorMetric: %.21f", diff11);
NSLog(@"PerceptualHashErrorMetric: %.21f", diff12);
DestroyMagickWand(magick_wand_1);
DestroyMagickWand(magick_wand_2);
DestroyMagickWand(magick_wand_3);
MagickWandTerminus();
}
5 observe output to the debugger (obviously, you'll need another method that uses some sort of "threshhold" monitor in order to determine what level shows an "exact or close to match" vs what you will consider a match yourself). Also, VERY IMPORTANT NOTE, the reason I have a "size_t" variable for size in the method inputs above is because you can't compare images of different sizes, so you must first resize the images you are comparing to a size that you feel is "reasonable" and then both images will be resized using ImageMagick to then compare the images:
Example 1:
[self compareTwoImages:[UIImage imageNamed:@"book.png"]
secondImage:[UIImage imageNamed:@"book.png"]
comparitorSize:32];
[76233:1364823] UndefinedMetric: 0.866871957624008593335
[76233:1364823] AbsoluteErrorMetric: 0.000000000000000000000
[76233:1364823] MeanAbsoluteErrorMetric: 0.000000000000000000000
[76233:1364823] MeanErrorPerPixelMetric: 0.000000000000000000000**
[76233:1364823] MeanSquaredErrorMetric: 0.000000000000000000000
[76233:1364823] PeakAbsoluteErrorMetric: 0.000000000000000000000
[76233:1364823] PeakSignalToNoiseRatioMetric: inf
[76233:1364823] RootMeanSquaredErrorMetric: 0.866871957624008593335
[76233:1364823] NormalizedCrossCorrelationErrorMetric:
0.000000000000000000000
[76233:1364823] FuzzErrorMetric: 0.000000000000000000000
[76233:1364823] UndefinedErrorMetric: 0.866871957624008593335
[76233:1364823] PerceptualHashErrorMetric: 0.000000000000000000000
Example 2:
[self compareTwoImages:[UIImage imageNamed:@"book.png"]
secondImage:[UIImage imageNamed:@"arrow.png"]
comparitorSize:32];
[76338:1368754] UndefinedMetric: 0.074585376822533272501
[76338:1368754] AbsoluteErrorMetric: 795.000000000000000000000
[76338:1368754] MeanAbsoluteErrorMetric: 0.314410045058480136504
[76338:1368754] MeanErrorPerPixelMetric: 328395.000000000000000000000
[76338:1368754] MeanSquaredErrorMetric: 0.245338692857198115149
[76338:1368754] PeakAbsoluteErrorMetric: 1.000000000000000000000
[76338:1368754] PeakSignalToNoiseRatioMetric: 6.102339529383479899138
[76338:1368754] RootMeanSquaredErrorMetric: 0.074585376822533272501
[76338:1368754] NormalizedCrossCorrelationErrorMetric: 0.000000000000000000000
[76338:1368754] FuzzErrorMetric: 0.571942529580490965913
[76338:1368754] UndefinedErrorMetric: 0.074585376822533272501
[76338:1368754] PerceptualHashErrorMetric: 1827.005561849247442296473
There's quite a bit going on here mathematically. I don't have time to explain all these variables, but suffice it to say, that this comparison between two images uses some very well known methods to compare two images. You'll have to pick it up from here and test out the statistics to customize this to your liking and to choose a threshold of error that suits your purposes.
Quick explanation:
ImageMagick is a battle tested image processing library, and while these methods listed above are sort of "black box" it this black boxness that allows you to save time vs moving to something that uses OpenCV. ImageMagick has already established some very good image processing algorithms and it's this history along with the out-of-the-box "this method works" that is one of the biggest benefits of ImageMagick considering what it would take for you to develop your own image recognition/processing library or methods. (by the way, I'm not affiliated with ImageMagick, I'm just very happy with the product, that's all)
The methods used in the Objective-C methods above are methods that stem from the ImageMagick Library for IOS. You'll have to read up on these methods but just so you know, they are written in C and not Objective-C which means that some of this is sort of foreign to the run of the mill Image I/O or other processing libraries. However, the only portion that I see as being hard to understand (assuming a person is new to C code) are how to understand what the "&" symbol is doing in front of some variables. Other than this, there's the issue of declaring and using structs, but this can easily be answered by using Stack Overflow, there's a lot of info on this right here.
I don't like the idea of you having to write your own library or image processing algorithms for an app like this. I think you are doing a very good thing for a person in need and I think it will help out a great number of people if you can lock down an MVP and I think that using ImageMagick is going to help you get there a lot sooner than needing to rewrite some of the stuff that ImageMagick already does for your own purposes.
One last thing to note, ImageMagick is built on some very low level C libraries. I would need to run a processing comparison of some sort to determine how well ImageMagick performs on IOS devices versus something like Image I/O. However, I have a feeling that these two image processing libraries share some of the same image processing functionality and speed. Correct me if anyone is certain that Image I/O is definately faster in tests, but I'm merely telling you this so you know that this ISN'T your average POD install, this is a robust piece of machinary that by the graces of some IOS devs they made an IOS version basically drop in using CoccoaPods. Beyond this, ImageMagick is used on all computing platforms and is largely a command line tool
Statistics, what the numbers mean:
Here's the resources you'll need to understand the math behind the statistics that I'm showing above in the debugger output:
This first one is old, but still relevant:
http://www.ict.griffith.edu.au/anthony/info/graphics/image_comparing
This one seems to be up to date:
http://www.imagemagick.org/Usage/compare/
Whether you choose to use this library or another, good luck to you, I like where you are going with this app and your demo looks amazing!
EDIT: I almost forgot to tell you the most important part here .. if the statistics return all "zeros" for everything except for "UndefinedMetric", "PeakSignalToNoiseRatioMetric", "RootMeanSquaredErrorMetric", and "UndefinedErrorMetric", then you MORE than likely have a MATCH!