如何比较两个UIImage对象

我正在开发一个应用程序。在那里我使用imageviews .SO之前UIImageview图像我需要在UIimage obejct中获取该图像,并与另一个UIImage对象进行比较,find两者都是山姆或不。 所以请告诉我如何做到这一点。

一种方法是先将它们转换为图像数据,然后进行比较。

 - (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2 { NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); return [data1 isEqual:data2]; } 

@ Simon的答案的快速实现:

 func image(image1: UIImage, isEqualTo image2: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(image1)! let data2: NSData = UIImagePNGRepresentation(image2)! return data1.isEqual(data2) } 

或者根据@ nhgrif的build议来扩展UIImage:

 import UIKit extension UIImage { func isEqualToImage(image: UIImage) -> Bool { let data1: NSData = UIImagePNGRepresentation(self)! let data2: NSData = UIImagePNGRepresentation(image)! return data1.isEqual(data2) } } 

当同时使用[UIImage imageNamed:] ,我们可以使用isEqual:否则我们可以比较数据。

最初比较图像大小

对于较便宜的方法,请首先比较图像大小。 即使图像内部有小的变化,尺寸也会不同。

 NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); if(data1.length == data2.length) { // if required, compare the data to confirm it if(data1 isEqual:data2) { // images are exactly same } else { // even though size is same images are different } } else { // images are different. } 

在比较来自同一来源的图像(相同尺寸,格式等)下成功进行testing。

正确的答案取决于“你想做什么样的比较?”。

  1. 最简单的方法就是比较数据。
  2. 如果你想知道图像是从一个本地文件创build的 – 你可以使用-isEqual :(但是有一个危险的方法,因为我不确定,如果图像caching由于某种原因而被清除会发生什么)。
  3. 困难的方法是提供每像素比较 (当然,系统将花费更多的时间)。 由于法律原因,我无法提供我们公司的图书馆的代码:(

但是你可以在这里检查facebook的ios-snapshot-test-case项目的好例子: 右键连接到需要的文件 。 您可以使用性能testing来衡量处理时间。

对于伟大的正义,我会从下面复制代码:

 - (BOOL)fb_compareWithImage:(UIImage *)image tolerance:(CGFloat)tolerance { NSAssert(CGSizeEqualToSize(self.size, image.size), @"Images must be same size."); CGSize referenceImageSize = CGSizeMake(CGImageGetWidth(self.CGImage), CGImageGetHeight(self.CGImage)); CGSize imageSize = CGSizeMake(CGImageGetWidth(image.CGImage), CGImageGetHeight(image.CGImage)); // The images have the equal size, so we could use the smallest amount of bytes because of byte padding size_t minBytesPerRow = MIN(CGImageGetBytesPerRow(self.CGImage), CGImageGetBytesPerRow(image.CGImage)); size_t referenceImageSizeBytes = referenceImageSize.height * minBytesPerRow; void *referenceImagePixels = calloc(1, referenceImageSizeBytes); void *imagePixels = calloc(1, referenceImageSizeBytes); if (!referenceImagePixels || !imagePixels) { free(referenceImagePixels); free(imagePixels); return NO; } CGContextRef referenceImageContext = CGBitmapContextCreate(referenceImagePixels, referenceImageSize.width, referenceImageSize.height, CGImageGetBitsPerComponent(self.CGImage), minBytesPerRow, CGImageGetColorSpace(self.CGImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast ); CGContextRef imageContext = CGBitmapContextCreate(imagePixels, imageSize.width, imageSize.height, CGImageGetBitsPerComponent(image.CGImage), minBytesPerRow, CGImageGetColorSpace(image.CGImage), (CGBitmapInfo)kCGImageAlphaPremultipliedLast ); if (!referenceImageContext || !imageContext) { CGContextRelease(referenceImageContext); CGContextRelease(imageContext); free(referenceImagePixels); free(imagePixels); return NO; } CGContextDrawImage(referenceImageContext, CGRectMake(0, 0, referenceImageSize.width, referenceImageSize.height), self.CGImage); CGContextDrawImage(imageContext, CGRectMake(0, 0, imageSize.width, imageSize.height), image.CGImage); CGContextRelease(referenceImageContext); CGContextRelease(imageContext); BOOL imageEqual = YES; // Do a fast compare if we can if (tolerance == 0) { imageEqual = (memcmp(referenceImagePixels, imagePixels, referenceImageSizeBytes) == 0); } else { // Go through each pixel in turn and see if it is different const NSInteger pixelCount = referenceImageSize.width * referenceImageSize.height; FBComparePixel *p1 = referenceImagePixels; FBComparePixel *p2 = imagePixels; NSInteger numDiffPixels = 0; for (int n = 0; n < pixelCount; ++n) { // If this pixel is different, increment the pixel diff count and see // if we have hit our limit. if (p1->raw != p2->raw) { numDiffPixels ++; CGFloat percent = (CGFloat)numDiffPixels / pixelCount; if (percent > tolerance) { imageEqual = NO; break; } } p1++; p2++; } } free(referenceImagePixels); free(imagePixels); return imageEqual; } 

Swift 3

有两种方法。 喜欢:-

1)使用isEqual()函数。

  self.image?.isEqual(UIImage(named: "add-image")) 

2)使用accessibilityIdentifier

将accessibilityIdentifier设置为图像名称

 myImageView.image?.accessibilityIdentifier = "add-image" 

然后使用下面的代码。

 extension UIImageView { func getFileName() -> String? { // First set accessibilityIdentifier of image before calling. let imgName = self.image?.accessibilityIdentifier return imgName } } 

最后,找出方法的调用方式

 myImageView.getFileName() 

我的首选(Swift)解决scheme

 import UIKit func ==(lhs: UIImage, rhs: UIImage) -> Bool { guard let data1 = UIImagePNGRepresentation(lhs), data2 = UIImagePNGRepresentation(rhs) else { return false } return data1.isEqual(data2) } 

将图像转换为JPG / PNG格式,或者依赖辅助function标识符,要么是昂贵的操作,要么脆弱,容易出错。

在这里,我遵循苹果提供的build议在以下链接 :

isEqual( :)方法是确定两个图像是否包含相同图像数据的唯一可靠方法。 即使使用相同的caching图像数据初始化它们,您创build的图像对象也可能彼此不同。 确定其平等的唯一方法是使用isEqual( :)方法,它比较实际的图像数据。 清单1展示了比较图像的正确和不正确的方法。

为了简化,我创build了下面的扩展来进行比较,以便我可以避免转换第一个图像的问题:

 import UIKit extension UIImage { func isEqual(to image: UIImage) -> Bool { return isEqual(image) } } 

有了这个,我现在可以设置一个例子来比较一对图像:

 let imageA = UIImage(named: "a")! let imageB = UIImage(named: "b")! let imageC = UIImage(named: "a")! print(imageA.isEqual(to: imageA)) // true print(imageA.isEqual(to: imageC)) // true print(imageA.isEqual(to: imageB)) // false 

我不确定如何比较UIImage数据,因为它是昂贵的。 你可以做的是子类Uimage并添加标签属性你自己,然后比较标签之前更改图像。 分配

那么你也可以使用“标签”属性来识别程序后期的对象。 只要设置整数值,你就可以走了

如果你知道一个图像名称,它会帮助你….

 CGImageRef cgImage = [imageView.image CGImage]; if (cgImage == [UIImage imageNamed:@"imagename.png"].CGImage) { // True Statement }