2012-08-22 3 views
34

Ich baue eine App, die Menschen ein Bild von sich selbst vor einem weißen Hintergrund hochladen können und die App wird eine Silhouette der Person erstellen.Luma Key (Erstellen Alpha-Maske aus Bild) für iOS

Ich habe eine harte Zeit, den Hintergrund auszutasten. Ich verwende das GPUImage Rahmen und das GPUImageChromaKeyBlendFilter funktioniert gut für Farben, aber wenn Sie zu weiß/schwarz kommen, ist es wirklich schwer, eine dieser Farben auszumachen. Wenn ich den Schlüssel auf weiß oder schwarz setze, ist es gleich.

Irgendwelche Ratschläge?

+1

Wo ist @ [Brad Larson] (http://Stackoverflow.com/users/19679/brad-larson), wenn Sie ihn brauchen! –

+0

Versuchen Sie, einen benutzerdefinierten Filter zu erstellen, der auf dem GPUImageAlphaBlendFilter basiert und nur den Alphakanal ('textureColor.a') in der letzten Mischoperation durch den roten Kanal ersetzt (' textureColor.r'). Wenn Sie Ihr Bild in Luminanz umgewandelt haben, bevor Sie es in dieses Bild einfügen, sollte es meiner Ansicht nach selektiv auf der Leuchtdichte des ersten Bildes basieren. Möglicherweise müssen Sie die Mischreihenfolge optimieren, um den gewünschten Effekt zu erzielen. –

+0

Vielen Dank für Ihre Zeit! Leider stürzt die App jetzt ab. Um klar zu sein, ist dies die Zeile, auf die Sie sich beziehen: gl_FragColor = vec4 (mix (textureColor.rgb, textureColor2.rgb, textureColor2.a * mischungPercent), textureColor.a); Wie gebe ich nur rot? Alles, was ich versuchte, endete mit einem Absturz: Assertionsfehler in - [GPUImageAlphaBlendFilter initWithVertexShaderFromString: fragmentShaderFromString:] –

Antwort

0

Also, einen weißer transparent ändern wir diese Methode verwenden können:

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

und den nicht transparenten Pixel mit schwarz zu ersetzen, können wir verwenden:

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

so in der Praxis dieser wäre:

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

Offensichtlich würden Sie dies in einem Hintergrundthread nennen, um alles runnin zu halten g reibungslos.

0

Ein Spiel mit Quartz Composer und den CoreImage-Filtern kann Ihnen helfen. Ich glaube, dass dieser Code sollten Sie eine Silhouette machen:

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

Manchmal ist eine Klärung dessen, was Sie versuchen, zu verstehen, zu erreichen und dann die Unterschiede helfen könnte. Sie sprechen von dem, was ich Transluzenz versus Transparenz erhalte.

Transluzenz berücksichtigt Alpha, damit der Hintergrund mit dem Vordergrund gemischt werden kann, basierend auf dem Alpha-Wert für die Bildpixel und der Art der Auswertung im Hintergrundpuffer.

Durch die Transparenz kann ein Bild in den Bereichen mit einem harten Alpha und Schwellenwert "maskiert" werden, und der Hintergrund kann ohne Überblendung durch die Maske gesehen werden. Der Schwellenwert ermöglicht eine begrenzte Mischung basierend auf dem Alpha-Wert bis zum Schwellenwert.

Chromokeying ist wie Transparenz, da Sie eine fest codierte Farbe als Maskenfarbe (oder Alpha-Schwelle für gemischte Keying) festlegen können. Dadurch kann Hintergrund durch Teile des Vordergrunds gesehen werden, die diese Farbe besitzen.

Wenn das Bildformat, den Datentyp oder Pixelformat für die Alpha-Wert unterstützt, ist es ziemlich trivial zu berechnen:

Alpha basierend auf Leuchtstärke = (R + G + B)/3;

Alpha basierend auf der Kanalpräsidentschaft = Max (R, G, B);

Blended Transparenz mit einer Alpha-Schwelle von 127 würde bedeuten, dass jedes Pixel, das den Alpha-Test mit einem Wert von 127 oder niedriger bestanden hat, gemischt wird und dass die über 127 schwer maskiert werden.

Ich hoffe, dass hilft ein wenig zu klären, nur für den Fall, dass es nicht klar ist. Super Code Jungs.

1

Es gibt einen Grund, warum in der Filmproduktion für die Chroma-Keying-Funktion typischerweise blaue oder grüne Bildschirme anstelle von Weiß verwendet werden.Auf einem Foto kann alles weiß oder weiß genug sein, besonders Augen oder Highlights oder nur Teile der Haut. Außerdem ist es ziemlich schwierig, eine gleichmäßige weiße Wand ohne Schatten zu finden, die zumindest von Ihrem Motiv geworfen wird. Ich würde empfehlen, ein Histogramm zu erstellen, die am häufigsten verwendete Farbe unter den hellsten zu finden und dann mit einem bestimmten Schwellenwert nach dem größten Bereich dieser Farbe zu suchen. Dann füllen Sie eine Flut von diesem Bereich, bis ausreichend unterschiedliche Farben angetroffen werden. All das kann in der Software recht einfach durchgeführt werden, es sei denn, Sie möchten einen Echtzeit-Videostream.