Cómo comparar dos objects UIImage

Estoy desarrollando una aplicación. En eso estoy usando las imageviews .SO antes de cambiar la image UIImageview , necesito tomar esa image en UIimage obejct y comparar con otro object UIImage para encontrar que ambos son sam o no. Entonces, dígame cómo hacer eso.

Una forma es convertirlos a los datos de imágenes primero y luego compararlos.

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

Una implementación rápida de la respuesta de @ Simon:

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

O extendiendo UIImage basado en la sugerencia de @nhgrif:

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

cuando ambos utilizan [UIImage imageNamed:] , podemos usar isEqual: contrario, podríamos comparar los datos.

Compara inicialmente el tamaño de la image

Para un método less costoso, compare inicialmente el tamaño de la image. Incluso si hay un pequeño cambio dentro de una image, el tamaño será diferente.

 NSData *data1 = UIImagePNGRepresentation(image1); NSData *data2 = UIImagePNGRepresentation(image2); if(data1.length == data2.length) { // if requinetworking, 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. } 

Probado con éxito al comparar imágenes de la misma fuente (misma dimensión, formatting, etc.).

La respuesta correcta depende de "¿Qué tipo de comparación quieres hacer?".

  1. La forma más fácil es solo para comparar datos.
  2. Si desea saber si la image se creó a partir de un file local , puede usar -isEqual: (pero hay una forma peligrosa, porque no estoy seguro, qué pasa si la image se cierra por algún motivo).
  3. La forma más difícil es proporcionar una comparación por píxel (seguramente, el sistema pasará más time en él). No puedo proporcionar el código de la biblioteca de nuestra empresa debido a razones legales 🙁

Pero puede verificar un buen ejemplo en el proyecto ios-snapshot-test-case de Facebook aquí: enlace a la derecha del file necesario . Puede usar testings de performance para medir el time del process.

Para la Gran Justicia copyré el código de allí abajo:

 - (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

Hay dos forms Me gusta:-

1) Usa la function isEqual ().

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

2) Use accessibilityIdentifier

Establezca accessibilityIdentifier como nombre de image

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

Luego usa el siguiente código.

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

Finalmente, el modo de identificación del método para identificar

 myImageView.getFileName() 

Mi solución preferida (Swift)

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

Convertir las imágenes a JPG / PNG, o confiar en los identificadores de accesibilidad es una operación costosa, o frágil y propensa a fallar.

Aquí, sigo la sugerencia provista por Apple en el siguiente enlace :

El método isEqual ( 🙂 es la única forma confiable para determinar si dos imágenes contienen los mismos datos de image. Los objects de image que cree pueden ser diferentes entre sí, incluso cuando los inicializa con los mismos datos de imágenes en caching. La única forma de determinar su igualdad es usar el método isEqual ( :), que compara los datos de image reales. El Listado 1 ilustra las forms correctas e incorrectas de comparar imágenes.

Para simplificar las cosas, creo la siguiente extensión para realizar comparaciones, de modo que pueda evitar el problema de convertir la primera image:

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

Con esto, ahora puedo configurar un ejemplo para compararlo en un par de imágenes:

 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 

No estoy seguro de comparar los datos de UIImage, ya que sería muy costoso. Lo que puedes hacer es subclass Uimage y agregar la propiedad de label tú mismo y luego comparar la label antes de cambiar la image. asignar

Bueno, también puede la propiedad 'label' para identificar los objects en las últimas etapas de su progtwig. Simplemente establezca el valor integer y está listo para usar.

si se conoce un nombre de image, lo ayudará.

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