鉴于这个库已经存在了很长时间并且似乎维护得很好,可能有助于解决问题的一种方法是使用ImageMagick。让我来演示一下。
1. 使用以下命令安装Pod:
pod 'ImageMagick', '6.8.8-9'
在视图控制器或其他您想要比较图像的视图中,导入以下内容:
#import <wand/MagickWand.h>
创建易于模式的异常“宏”,以便在不必每次编写异常方法时即可检查异常错误:
#define ThrowWandException(wand) { \
char * description; \
ExceptionType severity; \
\
description = MagickGetException(wand,&severity); \
(void) fprintf(stderr, "
description = (char *) MagickRelinquishMemory(description); \
exit(-1); \
}
3 创建比较方法,以比较两个图像:
-(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();
}
观察调试器的输出(显然,你需要另一种方法来使用某种“阈值”监视器来确定哪个级别显示“精确或接近匹配”,而不是你自己认为的匹配)。非常重要的一点是,在上面的方法输入中我有一个“size_t”变量用于大小,因为您不能比较不同大小的图像,所以您必须首先将要比较的图像调整为您认为“合理”的大小,然后使用ImageMagick调整两个图像的大小,然后再进行比较。
示例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
例子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
这里有很多数学运算。我没有时间解释所有这些变量,但可以说,比较两个图像使用了一些非常著名的方法。你需要从这里开始测试统计数据,以便根据自己的需求自定义并选择适合你目的的误差阈值。
简单解释:
ImageMagick 是一个经过实战检验的图像处理库,虽然上面列出的这些方法有点“黑盒子”的意味,但正是这种黑盒性质使你节省了时间,而不必转向使用 OpenCV 等其他库。ImageMagick 已经建立了一些非常好的图像处理算法,正是这种历史和开箱即用的“此方法可行”是 ImageMagick 的最大优势之一,考虑到开发自己的图像识别/处理库或方法所需付出的代价。 (顺便说一下,我与 ImageMagick 没有关联,我只是对产品非常满意)
Objective-C 方法中使用的方法源于 ImageMagick Library for IOS。你需要阅读这些方法,但是要知道,它们是用 C 编写的,而不是 Objective-C,这意味着某些内容对于普通的图像 I/O 或其他处理库来说有些陌生。然而,我认为唯一难以理解的部分(假设一个人对 C 代码不熟悉)是如何理解一些变量前面的“&”符号。除此之外,还有声明和使用结构体的问题,但这可以很容易地通过使用 Stack Overflow 来回答,这里有很多相关信息。
我不喜欢你必须为此类应用程序编写自己的库或图像处理算法的想法。我认为你正在为需要帮助的人做一件非常好的事情,如果你能锁定一个 MVP 并使用 ImageMagick,我认为它将比需要重新编写 ImageMagick 已经为你的目的做的一些工作更快地到达那里。
最后一件事要注意的是,ImageMagick 是建立在一些非常低级别的 C 库上的。我需要运行某种处理比较来确定 ImageMagick 在 IOS 设备上的表现与 Image I/O 等内容相比如何。然而,我有一种感觉,这两个图像处理库共享一些相同的图像处理功能和速度。如果有人确定 Image I/O 在测试中绝对更快,请纠正我,但我只是告诉你,这不是你平均的 POD 安装,这是一个强大的机器,幸运的是一些 IOS 开发者他们使用 CoccoaPods 做了一个 IOS 版本。除此之外,ImageMagick 用于所有计算平台,主要是一个命令行工具。
统计数据,数字的含义:
这里是您需要了解调试器输出中显示的统计学背后的数学的资源:
第一个资源已经过时,但仍然相关:
这个链接似乎是最新的:
http://www.imagemagick.org/Usage/compare/
无论您选择使用此库还是其他库,祝您好运。我很喜欢您的应用程序和演示看起来非常惊人!
编辑:我几乎忘了告诉你最重要的一点...如果统计数据返回除了“UndefinedMetric”,“PeakSignalToNoiseRatioMetric”,“RootMeanSquaredErrorMetric”和“UndefinedErrorMetric”之外的所有内容都是“零”,那么你可能已经找到了匹配的图像!