2010-10-10 15 views
7

¿Cómo puedo detectar la diferencia entre 2 imágenes, creando una máscara del área diferente para procesar el área común a ambas imágenes (desenfoque gaussiano, por ejemplo)?Crear una máscara a partir de la diferencia entre dos imágenes (iPhone)

sketch

EDIT: actualmente estoy usando este código para obtener el valor RGBA de píxeles:

+ (NSArray*)getRGBAsFromImage:(UIImage*)image atX:(int)xx andY:(int)yy count:(int)count 
{ 
    NSMutableArray *result = [NSMutableArray arrayWithCapacity:count]; 

    // First get the image into your data buffer 
    CGImageRef imageRef = [image CGImage]; 
    NSUInteger width = CGImageGetWidth(imageRef); 
    NSUInteger height = CGImageGetHeight(imageRef); 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    unsigned char *rawData = malloc(height * width * 4); 
    NSUInteger bytesPerPixel = 4; 
    NSUInteger bytesPerRow = bytesPerPixel * width; 
    NSUInteger bitsPerComponent = 8; 
    CGContextRef context = CGBitmapContextCreate(rawData, width, height, 
        bitsPerComponent, bytesPerRow, colorSpace, 
        kCGImageAlphaPremultipliedLast | kCGBitmapByteOrder32Big); 
    CGColorSpaceRelease(colorSpace); 

    CGContextDrawImage(context, CGRectMake(0, 0, width, height), imageRef); 
    CGContextRelease(context); 

    // Now your rawData contains the image data in the RGBA8888 pixel format. 
    int byteIndex = (bytesPerRow * yy) + xx * bytesPerPixel; 
    for (int ii = 0 ; ii < count ; ++ii) 
    { 
     CGFloat red = (rawData[byteIndex]  * 1.0)/255.0; 
     CGFloat green = (rawData[byteIndex + 1] * 1.0)/255.0; 
     CGFloat blue = (rawData[byteIndex + 2] * 1.0)/255.0; 
     CGFloat alpha = (rawData[byteIndex + 3] * 1.0)/255.0; 
     byteIndex += 4; 

     UIColor *acolor = [UIColor colorWithRed:red green:green blue:blue alpha:alpha]; 
     [result addObject:acolor]; 
    } 

    free(rawData); 

    return result; 
} 

El problema es que las imágenes se capturan desde la cámara del iPhone para que no son exactamente la misma posición. Necesito crear áreas de un par de píxeles y extraer el color general del área (¿tal vez sumando los valores RGBA y dividiendo por el número de píxeles?). ¿Cómo podría hacer esto y luego traducirlo a CGMask?

Sé que esta es una pregunta compleja, por lo que cualquier ayuda es apreciada.

Gracias.

Respuesta

6

Creo que la forma más sencilla de hacer esto sería usar un modo de mezcla diferente. El siguiente código se basa en el código que uso en CKImageAdditions.

+ (UIImage *) differenceOfImage:(UIImage *)top withImage:(UIImage *)bottom { 
    CGImageRef topRef = [top CGImage]; 
    CGImageRef bottomRef = [bottom CGImage]; 

    // Dimensions 
    CGRect bottomFrame = CGRectMake(0, 0, CGImageGetWidth(bottomRef), CGImageGetHeight(bottomRef)); 
    CGRect topFrame = CGRectMake(0, 0, CGImageGetWidth(topRef), CGImageGetHeight(topRef)); 
    CGRect renderFrame = CGRectIntegral(CGRectUnion(bottomFrame, topFrame)); 

    // Create context 
    CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); 
    if(colorSpace == NULL) { 
     printf("Error allocating color space.\n"); 
     return NULL; 
    } 

    CGContextRef context = CGBitmapContextCreate(NULL, 
               renderFrame.size.width, 
               renderFrame.size.height, 
               8, 
               renderFrame.size.width * 4, 
               colorSpace, 
               kCGImageAlphaPremultipliedLast); 
    CGColorSpaceRelease(colorSpace); 

    if(context == NULL) { 
     printf("Context not created!\n"); 
     return NULL; 
    } 

    // Draw images 
    CGContextSetBlendMode(context, kCGBlendModeNormal); 
    CGContextDrawImage(context, CGRectOffset(bottomFrame, -renderFrame.origin.x, -renderFrame.origin.y), bottomRef); 
    CGContextSetBlendMode(context, kCGBlendModeDifference); 
    CGContextDrawImage(context, CGRectOffset(topFrame, -renderFrame.origin.x, -renderFrame.origin.y), topRef); 

    // Create image from context 
    CGImageRef imageRef = CGBitmapContextCreateImage(context); 
    UIImage * image = [UIImage imageWithCGImage:imageRef]; 
    CGImageRelease(imageRef); 

    CGContextRelease(context); 

    return image; 
} 
+1

Hola Cory, el código es muy útil, logró producir los elementos que no están presentes en ninguna de las fotos. Sin embargo, parece que también produce un fondo negro, a diferencia de un fondo transparente. ¿Hay alguna manera de eliminar el fondo negro? – wahkiz

0

¿No puede simplemente restar valores de píxeles de las imágenes y procesar píxeles donde la diferencia i 0?

+0

@ Ross, gracias por su respuesta. Mi problema es que no sé cómo crear la máscara de los píxeles donde los valores de RGBA son diferentes. –

0

Pase por los píxeles, copie los que son diferentes en la imagen inferior a uno nuevo (no opaco).

Desenfoca la superior por completo, luego muestra la nueva de arriba.

+0

¿Cómo podría copiar los píxeles en una nueva imagen? –

0

Cada píxel que no tiene un píxel adecuadamente similar en la otra imagen dentro de un cierto radio se puede considerar como parte de la máscara. Es lento, (aunque no hay mucho más rápido) pero funciona de manera bastante simple.

2

Hay tres razones píxeles cambiará de un iPhone foto a la siguiente, el tema cambia, el iPhone se movió, y ruido aleatorio. Supongo que para esta pregunta, está más interesado en los cambios de tema, y ​​desea procesar los efectos de los otros dos cambios. También asumo que la aplicación pretende que el usuario mantenga el iPhone razonablemente quieto, por lo que los cambios de movimiento del iPhone son menos importantes que los cambios en el sujeto.

Para reducir los efectos del ruido aleatorio, solo difumine la imagen un poco. Una borrosidad promedia simple, donde cada píxel de la imagen resultante es un promedio del píxel original con sus vecinos más cercanos, debería ser suficiente para suavizar el ruido en una imagen de iPhone razonablemente bien iluminada.

Para abordar el movimiento del iPhone, puede ejecutar un algoritmo de detección de características en cada imagen (para comenzar, busque detección de características en Wikipedia). Luego calcule las transformaciones necesarias para alinear las características detectadas menos cambiadas.

Aplica que se transforman en las imágenes borrosas, y encuentran la diferencia entre las imágenes. Cualquier píxel con una diferencia suficiente se convertirá en tu máscara. Luego puede procesar la máscara para eliminar cualquier isla de píxeles modificados. Por ejemplo, un sujeto puede llevar una camisa de color sólido. El sujeto puede moverse de una imagen a la siguiente, pero el área de la camisa de color sólido puede superponerse, dando como resultado una máscara con un agujero en el medio.

En otras palabras, este es un problema de procesamiento de imágenes significativo y difícil.No encontrarás la respuesta en una publicación de stackoverflow.com. Encontrará la respuesta en un libro de texto de procesamiento de imágenes digitales.

+0

Gracias por su respuesta Sr. Berna. Sé que esta es una pregunta compleja y aprecio sus consejos. Definitivamente haré algunas investigaciones de procesamiento de imágenes para abordar este problema. –

Cuestiones relacionadas