2010-08-03 10 views
9

Come è possibile confrontare un'immagine con un'altra?Confronto di UIImage

Grazie!

+1

Quantificare "confronta". –

+0

Confronta i pixel o le bitmap per determinare se sono uguali. – user377419

risposta

2

Se si dispone di due UIImages, è necessario ottenere le loro rappresentazioni di quarzo CGImageRef da tali oggetti. Quindi creare due nuovi contesti bitmap supportati da un buffer di memoria creato e passato, uno per ciascuna delle immagini. Quindi utilizzare CGContextDrawImage per disegnare le immagini nei contesti bitmap. Ora i byte delle immagini sono nei buffer. È quindi possibile eseguire il ciclo manualmente o memcmp per verificare le differenze. propria spiegazione dettagliata e codice di esempio

di Apple in tutto la creazione di contesti bitmap e disegnare in loro è qui:

https://developer.apple.com/library/content/documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_context/dq_context.html

La differenza per voi è che si sta disegnando un'immagine esistente nel contesto. Utilizzare CGContextDrawImage per questo.

+1

Whoaaaa ... Quello è un po 'di confusione in non cercare un giro gratis (in realtà voglio imparare da questo) ma potresti pubblicare un po' di codice. Non sono davvero framillar con alcun metodo CG .. O almeno cercare di spiegarlo meglio per un noob. – user377419

+0

Ho aggiunto un link a buone informazioni. Se è ancora un po 'sopra la tua testa, dai un'occhiata ai tutorial e ai documenti di Apple sulle basi della Core Graphics. È un argomento troppo grande per rispondere come una domanda qui su SO, e devi capire che se stai facendo un lavoro sostanziale sull'immagine su iOS. –

+0

Erhm Questo era fonte di confusione ... Qualcuno ha detto che potevi semplicemente convertirlo in immagine binaria o solo in scala di grigi e confrontarlo. Potrei farlo? – user377419

2

qui 'esempio di codice s

-(NSMutableArray*)getImageBinary:(UIImage*)ImageToCompare 
{ 
    int i = 0;  
    int step = 4; 

    CGContextRef context = NULL; 
    CGColorSpaceRef colorSpace; 
    //void * bitmapData; 
    //int bitmapByteCount; 
    int bitmapBytesPerRow; 

    // Get image width, height. We'll use the entire image. 
    size_t pixelsWide = CGImageGetWidth(ImageToCompare.CGImage); 
    size_t pixelsHigh = CGImageGetHeight(ImageToCompare.CGImage); 

    // Declare the number of bytes per row. Each pixel in the bitmap in this 
    // example is represented by 4 bytes; 8 bits each of red, green, blue, and 
    // alpha. 
    bitmapBytesPerRow = (pixelsWide * 4); 
    NSMutableArray *firstImagearray=[[NSMutableArray alloc]init]; 

    //bitmapByteCount = (bitmapBytesPerRow * pixelsHigh); 

    // Use the generic RGB color space. 
    colorSpace = CGColorSpaceCreateDeviceRGB(); 

    if (colorSpace == NULL) 
    { 
     fprintf(stderr, "Error allocating color space\n"); 
     return nil; 
    } 

    // Allocate memory for image data. This is the destination in memory 
    // where any drawing to the bitmap context will be rendered. 
    //bitmapData = malloc(bitmapByteCount); 
    // if (bitmapData == NULL) 
    // { 
    //  fprintf (stderr, "Memory not allocated!"); 
    //  CGColorSpaceRelease(colorSpace); 
    //  return NULL; 
    // } 

    // Create the bitmap context. We want pre-multiplied ARGB, 8-bits 
    // per component. Regardless of what the source image format is 
    // (CMYK, Grayscale, and so on) it will be converted over to the format 
    // specified here by CGBitmapContextCreate. 
    context = CGBitmapContextCreate (NULL, 
            pixelsWide, 
            pixelsHigh, 
            8,  // bits  per component 
            bitmapBytesPerRow, 
            colorSpace, 
            kCGImageAlphaPremultipliedFirst); 

    if (context == NULL) 
    { 
     //free (bitmapData); 
     fprintf (stderr, "Context not created!"); 
    } 

    CGRect rect = {{0,0},{pixelsWide, pixelsHigh}}; 
    // 
    // Draw the image to the bitmap context. Once we draw, the memory 
    // allocated for the context for rendering will then contain the 
    // raw image data in the specified color space. 
    CGContextDrawImage(context, rect, ImageToCompare.CGImage); 

    // Make sure and release colorspace before returning 
    CGColorSpaceRelease(colorSpace); 
    /////********** 
    size_t _width = CGImageGetWidth(ImageToCompare.CGImage); 
    size_t _height = CGImageGetHeight(ImageToCompare.CGImage); 

    unsigned char* data = CGBitmapContextGetData (context); 

    if (data != NULL) 
    { 
     int max = _width * _height * 4; 

     for (i = 0; i < max; i+=step) 
     { 
      [firstImagearray addObject:[NSNumber numberWithInt:data[i + 0]]]; 
      [firstImagearray addObject:[NSNumber numberWithInt:data[i + 1]]]; 
      [firstImagearray addObject:[NSNumber numberWithInt:data[i + 2]]]; 
      [firstImagearray addObject:[NSNumber numberWithInt:data[i + 3]]];  } 
    } 

    if (context == NULL) 
     // error creating context 
    return nil; 


    //if (data) { free(data); } 
    if (context) { 
     CGContextRelease(context); 
    } 
    return firstImagearray; 
} 

-(BOOL)Compare:(UIImage*)ImageToCompare secondImage:(UIImage*)secondImage 
{ 
    ImageToCompare=[ImageToCompare scaleToSize:CGSizeMake(self.appdelegate.ScreenWidth,self.appdelegate.ScreenHeigth)]; 
    secondImage=[secondImage scaleToSize:CGSizeMake(self.appdelegate.ScreenWidth, self.appdelegate.ScreenHeigth)]; 

    NSArray *first=[[NSArray alloc] initWithArray:(NSArray *)[self getImageBinary:ImageToCompare]]; 
    NSArray *second=[[NSArray alloc] initWithArray:(NSArray *)[self getImageBinary:secondImage]]; 

    for (int x=0; x<first.count; x++) 
    { 
     if ([((NSNumber*)[first objectAtIndex:x]) intValue] ==[((NSNumber*)[second objectAtIndex:x]) intValue]) 
     { 

     } 
     else 
     { 
      return NO; 
     } 
    } 
    return YES; 
} 
2

Questo è quello che uso nel mio test di unità per confrontare le immagini. A differenza di altri metodi (ad esempio, UIImagePNGRepresentation), funziona anche se le immagini hanno uno spazio colore diverso (ad esempio, RGB e scala di grigi).

@implementation UIImage (HPIsEqualToImage) 

- (BOOL)hp_isEqualToImage:(UIImage*)image 
{ 
    NSData *data = [image hp_normalizedData]; 
    NSData *originalData = [self hp_normalizedData]; 
    return [originalData isEqualToData:data]; 
} 

- (NSData*)hp_normalizedData 
{ 
    const CGSize pixelSize = CGSizeMake(self.size.width * self.scale, self.size.height * self.scale); 
    UIGraphicsBeginImageContext(pixelSize); 
    [self drawInRect:CGRectMake(0, 0, pixelSize.width, pixelSize.height)]; 
    UIImage *drawnImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return UIImagePNGRepresentation(drawnImage); 
} 

@end 

Non è molto efficiente, così mi consiglia di non utilizzare nel codice di produzione meno che le prestazioni non è un problema.

+1

Sintesi completo: https://gist.github.com/hpique/dedb719817ac8c50afea – hpique

+0

se self è un UIImage, è possibile chiamare direttamente UIImagePNGRepresentation su di esso, senza disegnarlo prima. Vedi anche [converti UIImage in NSData e torna a UIImage] (http://stackoverflow.com/questions/20013144/convert-uiimage-to-nsdata-and-back-to-uiimage) – lazi74