Подтвердить что ты не робот

Как сравнить два объекта UIImage

Я разрабатываю одно приложение. В том, что я использую imageviews.SO перед изменением образа UIImageview, мне нужно взять это изображение в UIimage obejct и сравнить с другим объектом UIimage для нахождения обоих. sam или нет. Поэтому, пожалуйста, скажите мне, как это сделать.

4b9b3361

Ответ 1

Один из способов - сначала преобразовать их в данные изображения, а затем сравнить их.

- (BOOL)image:(UIImage *)image1 isEqualTo:(UIImage *)image2
{
    NSData *data1 = UIImagePNGRepresentation(image1);
    NSData *data2 = UIImagePNGRepresentation(image2);

    return [data1 isEqual:data2];
}

Ответ 2

Быстрая реализация ответа @Simon:

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

Или путем расширения UIImage на основе предложения @nhgrif:

import UIKit

extension UIImage {

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

}

Ответ 3

при использовании [UIImage imageNamed:], мы можем использовать isEqual:, иначе мы могли бы сравнить данные.

Ответ 4

Правильный ответ зависит от того, "Какое сравнение вы хотите сделать?".

  1. Самый простой способ - просто сравнить данные.
  2. Если вы хотите узнать, были ли изображения созданы из одного локального файла - вы можете использовать -isEqual: (но есть опасный способ, потому что я не уверен, что произойдет, если кэш изображений очистится для некоторых причина).
  3. Сложный способ - обеспечить сравнение с пикселями (конечно, система будет тратить на это больше времени). Я не могу предоставить код из библиотеки нашей компании по юридической причине :(

Но вы можете проверить хороший пример на Facebook ios-snapshot-test-case project здесь: ссылка прямо на нужный файл. Вы можете использовать тесты производительности для измерения времени процесса.

Для Великого Справедливости я скопирую код оттуда ниже:

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

Ответ 5

Обновленное решение Mark Tickner для Swift 4

import UIKit

extension UIImage {

    func isEqualToImage(_ image: UIImage) -> Bool {
        let data1 = self.pngData()
        let data2 = image.pngData()
        return data1 == data2
    }

}

Две переменные, вероятно, излишни, но они могут помочь объяснить кому-то новичку в этом. Можно сократить до:

import UIKit

extension UIImage {

    func isEqualToImage(_ image: UIImage) -> Bool {
        return self.pngData() == image.pngData()
    }

}

Ответ 6

Преобразование изображений в JPG/PNG или использование идентификаторов доступности - это либо дорогостоящая операция, либо хрупкая работа. склонен к неудаче.

Здесь я следую предложению Apple по следующей ссылке:

Метод isEqual (:) - единственный надежный способ определить, два изображения содержат одинаковые данные изображения. Объекты изображений, которые вы создаете могут отличаться друг от друга, даже если вы инициализируете их те же данные кэшированного изображения. Единственный способ определить их равенство это использовать метод isEqual (:), который сравнивает фактическое изображение данные. В листинге 1 показаны правильные и неправильные способы сравнения. изображения.

Чтобы упростить задачу, я создаю следующее расширение для проведения сравнений, чтобы избежать проблемы преобразования первого изображения:

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

Ответ 7

Я сделал некоторые изменения в ответе Mark и использовал Data и elementsEqual вместо NSData и isEqual.

extension UIImage {
    func isEqual(to image: UIImage) -> Bool {
        guard let data1: Data = UIImagePNGRepresentation(self),
            let data2: Data = UIImagePNGRepresentation(image) else {
                return false
        }
        return data1.elementsEqual(data2)
    }
}

Ответ 8

Мое предпочтительное (быстрое) решение

import UIKit

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

  return data1.isEqual(data2)
}

Ответ 9

Swift 3

Существует два способа. Как: -

1) Используйте функцию isEqual().

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

2) Используйте 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()

Ответ 10

Сравните исходный размер изображения

Для менее дорогостоящего метода сначала сравните размер изображения. Даже если внутри изображения небольшое изменение, размер будет другим.

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.
}

Успешно протестировано при сравнении изображений с одного источника (одинакового размера, формата и т.д.).

Ответ 11

Swift 4.x версия алгоритма сравнения Facebook:

/// Value in range 0...100 %
typealias Percentage = Float

// See: https://github.com/facebookarchive/ios-snapshot-test-case/blob/master/FBSnapshotTestCase/Categories/UIImage%2BCompare.m
private func compare(tolerance: Percentage, expected: Data, observed: Data) throws -> Bool {
    guard let expectedUIImage = UIImage(data: expected), let observedUIImage = UIImage(data: observed) else {
        throw Error.unableToGetUIImageFromData
    }
    guard let expectedCGImage = expectedUIImage.cgImage, let observedCGImage = observedUIImage.cgImage else {
        throw Error.unableToGetCGImageFromData
    }
    guard let expectedColorSpace = expectedCGImage.colorSpace, let observedColorSpace = observedCGImage.colorSpace else {
        throw Error.unableToGetColorSpaceFromCGImage
    }
    if expectedCGImage.width != observedCGImage.width || expectedCGImage.height != observedCGImage.height {
        throw Error.imagesHasDifferentSizes
    }
    let imageSize = CGSize(width: expectedCGImage.width, height: expectedCGImage.height)
    let numberOfPixels = Int(imageSize.width * imageSize.height)

    // Checking that our 'UInt32' buffer has same number of bytes as image has.
    let bytesPerRow = min(expectedCGImage.bytesPerRow, observedCGImage.bytesPerRow)
    assert(MemoryLayout<UInt32>.stride == bytesPerRow / Int(imageSize.width))

    let expectedPixels = UnsafeMutablePointer<UInt32>.allocate(capacity: numberOfPixels)
    let observedPixels = UnsafeMutablePointer<UInt32>.allocate(capacity: numberOfPixels)

    let expectedPixelsRaw = UnsafeMutableRawPointer(expectedPixels)
    let observedPixelsRaw = UnsafeMutableRawPointer(observedPixels)

    let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.premultipliedLast.rawValue)
    guard let expectedContext = CGContext(data: expectedPixelsRaw, width: Int(imageSize.width), height: Int(imageSize.height),
                                          bitsPerComponent: expectedCGImage.bitsPerComponent, bytesPerRow: bytesPerRow,
                                          space: expectedColorSpace, bitmapInfo: bitmapInfo.rawValue) else {
        expectedPixels.deallocate()
        observedPixels.deallocate()
        throw Error.unableToInitializeContext
    }
    guard let observedContext = CGContext(data: observedPixelsRaw, width: Int(imageSize.width), height: Int(imageSize.height),
                                          bitsPerComponent: observedCGImage.bitsPerComponent, bytesPerRow: bytesPerRow,
                                          space: observedColorSpace, bitmapInfo: bitmapInfo.rawValue) else {
        expectedPixels.deallocate()
        observedPixels.deallocate()
        throw Error.unableToInitializeContext
    }

    expectedContext.draw(expectedCGImage, in: CGRect(origin: .zero, size: imageSize))
    observedContext.draw(observedCGImage, in: CGRect(origin: .zero, size: imageSize))

    let expectedBuffer = UnsafeBufferPointer(start: expectedPixels, count: numberOfPixels)
    let observedBuffer = UnsafeBufferPointer(start: observedPixels, count: numberOfPixels)

    var isEqual = true
    if tolerance == 0 {
        isEqual = expectedBuffer.elementsEqual(observedBuffer)
    } else {
        // Go through each pixel in turn and see if it is different
        var numDiffPixels = 0
        for pixel in 0 ..< numberOfPixels where expectedBuffer[pixel] != observedBuffer[pixel] {
            // If this pixel is different, increment the pixel diff count and see if we have hit our limit.
            numDiffPixels += 1
            let percentage = 100 * Float(numDiffPixels) / Float(numberOfPixels)
            if percentage > tolerance {
                isEqual = false
                break
            }
        }
    }

    expectedPixels.deallocate()
    observedPixels.deallocate()

    return isEqual
}

Ответ 12

Этот метод прекрасно работает:

func isEqualImages(image1: UIImage, image2: UIImage) -> Bool {
    let data1: Data? = UIImagePNGRepresentation(image1)
    let data2: Data? = UIImagePNGRepresentation(image2)
    return data1 == data2
}

Ответ 13

Я не уверен в сравнении данных UIImage, поскольку это было бы дорого стоить. Что вы можете сделать, это подкласс Uimage и добавить свойство тега, а затем сравнить тег перед изменением изображения. назначить

Ответ 14

Swift 5.x

Вы можете просто использовать

let image: UIImage!
let anotherImage: UIImage!

image == anotherImage

Ответ 15

если вам известное имя одного изображения, это поможет вам....

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

Ответ 16

Ну, вы также можете использовать свойство "tag" для идентификации объектов на последних этапах вашей программы. Просто установите целочисленное значение, и вам хорошо идти