2012-08-22 16 views
34

Sto costruendo un'app che consente alle persone di caricare un'immagine di se stessi su uno sfondo bianco e l'app creerà una silhouette della persona.Luma Key (crea maschera alfa da immagine) per iOS

Ho difficoltà a digitare lo sfondo. Sto usando il framework GPUImage e lo GPUImageChromaKeyBlendFilter funziona perfettamente per i colori, ma se si arriva al bianco/nero è davvero difficile definire uno di quei colori. Se imposto la chiave su bianco o nero, le chiavi sono entrambe uguali.

Qualche consiglio?

+1

Dov'è @ [Brad Larson] (http://stackoverflow.com/users/19679/brad-larson) quando hai bisogno di lui! –

+0

Provare a creare un filtro personalizzato basato su GPUImageAlphaBlendFilter, sostituendo solo il canale alfa ('textureColor.a') nell'ultima operazione di mix con il canale rosso (' textureColor.r'). Se hai convertito l'immagine in luminanza prima di alimentarla, credo che debba fondersi in modo selettivo sulla luminanza della prima immagine. Potrebbe essere necessario modificare l'ordine del mix per ottenere l'effetto desiderato. –

+0

Grazie mille per il tuo tempo! Sfortunatamente, l'app si sta bloccando ora. Per essere chiari, questa è la linea a cui ti riferisci: gl_FragColor = vec4 (mix (textureColor.rgb, textureColor2.rgb, textureColor2.a * mixturePercent), textureColor.a); Come posso passare solo in rosso? Tutto ciò che ho provato è finito in un crash: Errore di asserzione in - [GPUImageAlphaBlendFilter initWithVertexShaderFromString: fragmentShaderFromString:] –

risposta

0

Quindi, per cambiare un bianco a trasparente possiamo usare questo metodo:

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

e per sostituire i pixel non trasparenti con il nero, possiamo usare:

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

quindi in pratica questo sarebbe:

Ovviamente lo chiamereste in un thread in background, per mantenere tutto in esecuzione senza problemi.

0

Avere un gioco con il compositore Quartz e i filtri CoreImage può aiutarti. Credo che questo codice dovrebbe farvi una silhouette:

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

volte un chiarimento di ciò che si sta tentando di raggiungere e poi a comprendere le differenze potrebbero aiutare. Stai parlando di ciò che raccolgo traslucidità contro trasparenza.

La traslucenza tiene conto dell'alfa consentendo di fondere lo sfondo con il primo piano in base al valore alfa per i pixel dell'immagine e il tipo di valutazione eseguita sul buffer di sfondo.

La trasparenza consente di "mascherare" l'immagine nelle parti con un alfa e una soglia rigidi e consente di visualizzare lo sfondo attraverso la maschera senza fusione. Il valore di soglia consente una miscelazione limitata in base al valore alfa fino alla soglia.

Chromokeying è come una trasparenza poiché consente di impostare un colore codificato come colore della maschera (o soglia alfa per la fusione di tasti), che consente di vedere lo sfondo attraverso parti del primo piano che possiedono quel colore.

Se il formato immagine supporta il tipo di dati o PixelFormat per valori alfa, è abbastanza banale per calcolare:

Alpha basato su luminosità = (R + G + B)/3;

Alpha basato sulla presidenza canale = Max (R, G, B);

La trasparenza sfumata con una soglia alfa di 127 significherebbe che ogni pixel che superava il test alfa con un valore di 127 o inferiore sarebbe stato miscelato e quelli sopra 127 sarebbero stati mascherati.

Spero che questo aiuti a chiarire un po ', nel caso in cui non sia chiaro. Ragazzi fantastici.

1

C'è un motivo per cui in genere gli schermi blu o verdi vengono utilizzati nella produzione di filmati per la chroma keying, anziché il bianco.Qualsiasi cosa può essere bianca o sufficientemente vicina al bianco in una foto, in particolare occhi o luci o solo parti della pelle. Inoltre, è abbastanza difficile trovare un muro bianco uniforme senza ombre, proiettato almeno dal soggetto. Consiglierei di costruire un istogramma, trovando il colore più frequentemente usato tra quelli più brillanti, quindi cercare l'area più grande di quel colore usando qualche soglia. Quindi eseguire un riempimento di piena da quella zona finché non si incontrano colori sufficientemente diversi. Tutto ciò può essere fatto abbastanza facilmente nel software, a meno che tu non voglia un flusso video in tempo reale.