2012-08-22 7 views
34

Estoy construyendo una aplicación que permite a las personas subir una imagen de ellos mismos sobre un fondo blanco y la aplicación creará una silueta de la persona.Luma Key (crear máscara alfa a partir de la imagen) para iOS

Estoy teniendo dificultades para ver el fondo. Estoy usando el marco GPUImage y el GPUImageChromaKeyBlendFilter funciona muy bien para los colores, pero si llegas al blanco/negro es muy difícil sacar uno de esos colores. Si configuro la tecla en blanco o negro, ambas teclas son iguales.

¿Algún consejo?

+1

¿Dónde está @ [Brad Larson] (http://stackoverflow.com/users/19679/brad-larson) cuando lo necesites! –

+0

Intente crear un filtro personalizado basado en GPUImageAlphaBlendFilter, solo reemplazando el canal alfa ('textureColor.a') en la última operación de mezcla con el canal rojo (' textureColor.r'). Si ha convertido su imagen en luminancia antes de alimentar esto, creo que debería combinarse de manera selectiva según la luminancia de la primera imagen. Es posible que deba ajustar el orden de mezcla para lograr el efecto que desee también. –

+0

¡Muchas gracias por su tiempo! Lamentablemente, la aplicación se está bloqueando ahora. Para que quede claro, esta es la línea a la que se refiere: gl_FragColor = vec4 (mix (textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a); ¿Cómo solo paso en rojo? Todo lo que probé terminó con un bloqueo: Fallo de aserción en - [GPUImageAlphaBlendFilter initWithVertexShaderFromString: fragmentShaderFromString:] –

Respuesta

0

Así, para cambiar un blanco a transparente podemos utilizar este método:

-(UIImage *)changeWhiteColorTransparent: (UIImage *)image { 
    CGImageRef rawImageRef=image.CGImage; 

    const float colorMasking[6] = {222, 255, 222, 255, 222, 255}; 

    UIGraphicsBeginImageContext(image.size); 
    CGImageRef maskedImageRef=CGImageCreateWithMaskingColors(rawImageRef, colorMasking); 
    { 
     //if in iphone 
     CGContextTranslateCTM(UIGraphicsGetCurrentContext(), 0.0, image.size.height); 
     CGContextScaleCTM(UIGraphicsGetCurrentContext(), 1.0, -1.0); 
    } 

    CGContextDrawImage(UIGraphicsGetCurrentContext(), CGRectMake(0, 0, image.size.width, image.size.height), maskedImageRef); 
    UIImage *result = UIGraphicsGetImageFromCurrentImageContext(); 
    CGImageRelease(maskedImageRef); 
    UIGraphicsEndImageContext();  
    return result; 
} 

y para reemplazar los píxeles no transparentes con negro, podemos utilizar:

- (UIImage *) changeColor: (UIImage *)image { 
    UIGraphicsBeginImageContext(image.size); 

    CGRect contextRect; 
    contextRect.origin.x = 0.0f; 
    contextRect.origin.y = 0.0f; 
    contextRect.size = [image size]; 
    // Retrieve source image and begin image context 
    CGSize itemImageSize = [image size]; 
    CGPoint itemImagePosition; 
    itemImagePosition.x = ceilf((contextRect.size.width - itemImageSize.width)/2); 
    itemImagePosition.y = ceilf((contextRect.size.height - itemImageSize.height)); 

    UIGraphicsBeginImageContext(contextRect.size); 

    CGContextRef c = UIGraphicsGetCurrentContext(); 
    // Setup shadow 
    // Setup transparency layer and clip to mask 
    CGContextBeginTransparencyLayer(c, NULL); 
    CGContextScaleCTM(c, 1.0, -1.0); 
    CGContextClipToMask(c, CGRectMake(itemImagePosition.x, -itemImagePosition.y, itemImageSize.width, -itemImageSize.height), [image CGImage]); 

    CGContextSetFillColorWithColor(c, [UIColor blackColor].CGColor); 


    contextRect.size.height = -contextRect.size.height; 
    contextRect.size.height -= 15; 
    // Fill and end the transparency layer 
    CGContextFillRect(c, contextRect); 
    CGContextEndTransparencyLayer(c); 

    UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 
    return img; 
} 

por lo que en la práctica esto Sería:

-(UIImage *)silhouetteForImage:(UIImage *)img { 
    return [self changeColour:[self changeWhiteColorTransparent:img]]; 
} 

Obviamente, usted llamaría esto en un hilo de fondo, para mantener todo runnin g sin problemas.

0

Tener un juego con el compositor Quartz y los filtros CoreImage puede ser de ayuda. Creo que este código se debe hacer una silueta:

- (CGImageRef)silhouetteOfImage:(UIImage *)input 
{ 
    CIContext *ciContext = [CIContext contextWithOptions:nil]; 
    CIImage *ciInput = [CIImage imageWithCGImage:[input CGImage]]; 
    CIFilter *filter = [CIFilter filterWithName:@"CIFalseColor"]; 
    [filter setValue:[CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:1.0] forKey:@"inputColor0"]; 
    [filter setValue:[CIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.0] [email protected]"inputColor1"]; 
    [filter setValue:ciInput forKey:kCIInputImageKey]; 
    CIImage *outImage = [filter valueForKey:kCIOutputImageKey]; 
    CGImageRef result = [ciContext createCGImage:outImage fromRect:[ciInput extent]]; 
    return result; 
} 
0

veces una aclaración de lo que está tratando de lograr y luego la comprensión de las diferencias podrían ayudar. Estás hablando de lo que encuentro translucidez versus transparencia.

La translucidez tiene en cuenta el alfa permitiendo que el fondo se mezcle con el primer plano en función del valor alfa de los píxeles de la imagen y el tipo de evaluación realizada en el búfer de fondo.

La transparencia permite "enmascarar" una imagen en las partes con un alfa y un umbral difíciles, y permite que el fondo se vea a través de la máscara sin mezclar. El valor de umbral permite una combinación limitada basada en el valor alfa hasta el umbral.

Chromokeying es como la transparencia, ya que le permite establecer un color codificado como el color de la máscara (o umbral alfa para la combinación de claves), que permite ver el fondo a través de las partes del primer plano que poseen ese color.

Si su formato de imagen compatible con el tipo de datos o PixelFormat para valores alfa, es bastante trivial para calcular:

alfa basado en luminosidad = (R + G + B)/3;

Alpha basado en la presidencia del canal = Máx. (R, G, B);

La transparencia combinada con un umbral alfa de 127 significa que se mezclarán todos los píxeles que pasaron la prueba alfa con un valor de 127 o inferior y los que están por encima de 127 quedarán ocultos.

Espero que ayude a aclarar un poco, en caso de que no esté claro. Código impresionante chicos.

1

Existe un motivo por el que normalmente se utilizan pantallas azules o verdes en la producción de películas para la incrustación de croma, en lugar de blanco.Cualquier cosa puede ser blanca o lo suficientemente cerca del blanco en una foto, especialmente los ojos o reflejos o solo partes de la piel. Además, es bastante difícil encontrar una pared blanca uniforme sin sombras, al menos por el sujeto. Recomendaría construir un histograma, encontrar el color más utilizado entre los más brillantes, luego buscar el área más grande de ese color usando algún umbral. Luego haga un relleno de inundación desde esa área hasta que se encuentren colores suficientemente diferentes. Todo eso se puede hacer fácilmente en el software, a menos que desee una transmisión de video en tiempo real.

Cuestiones relacionadas