35 votes

Luma Key (créer un masque alpha à partir d'une image) pour iOS

Je construis une application qui permet aux gens de télécharger une image d'eux-mêmes sur un fond blanc et l'application va créer une silhouette de la personne.

J'ai du mal à saisir l'arrière-plan. J'utilise le cadre GPUImage et le GPUImageChromaKeyBlendFilter convient parfaitement aux couleurs, mais si vous utilisez le blanc / noir, il est vraiment difficile de sélectionner l'une de ces couleurs. Si je mets la clé en blanc ou en noir, les touches sont identiques.

Aucun conseil?

1voto

noop Points 150

Il y a une raison pour laquelle généralement bleu ou vert écrans sont utilisés dans la production de films pour l'incrustation, au lieu de blanc. Tout peut être blanc ou suffisamment proche du blanc dans une photo, surtout des yeux ou de reflets ou d'une partie de la peau. Aussi, il est assez difficile de trouver un uniforme mur blanc sans ombre, projetée par votre sujet au moins. Je recommande la construction d'un histogramme, pour trouver la plus frequenty utilisé la couleur parmi les plus brillants, ensuite, la recherche de la plus grande zone de couleur à l'aide d'un certain seuil. Puis faire un remplissage de la zone jusqu'à ce que suffisamment de couleurs différentes sont rencontrés. Tout cela peut être facilement fait dans le logiciel, sauf si vous voulez une vidéo en temps réel de flux.

0voto

Daniel. Points 91

Donc, pour changer un blanc en transparent, nous pouvons utiliser cette méthode:

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

et pour remplacer les pixels non transparents par du noir, nous pouvons utiliser:

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

Donc, dans la pratique, ce serait:

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

Évidemment, vous appelleriez cela dans un fil d’arrière-plan, pour que tout fonctionne sans heurts.

0voto

James Snook Points 903

Avoir une pièce avec Quartz Composer et les filtres CoreImage peut vous aider. Je crois que ce code devrait vous faire une 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] forKey@"inputColor1"];
  [filter setValue:ciInput forKey:kCIInputImageKey];
  CIImage *outImage = [filter valueForKey:kCIOutputImageKey];
  CGImageRef result = [ciContext createCGImage:outImage fromRect:[ciInput extent]];
  return result;
}
 

0voto

Brian Johns Points 21

Parfois, une clarification de ce que vous essayez d'atteindre et de comprendre les différences pourraient aider. Vous parlez de ce que je comprends de la translucidité rapport à la transparence.

La translucidité prend alpha en considération permettant l'arrière-plan pour être mélangé avec le premier plan basé sur la valeur alpha pour les pixels de l'image et de la nature de l'évaluation effectuée sur le tampon de fond.

La transparence permet à une image d'être "masqué" dans les parties avec un alpha et de seuil, et permet à l'arrière-plan pour être vu à travers le masque, sans les mélanger. La valeur de seuil permet limitée de fusion basée sur la valeur alpha jusqu'au seuil.

Chromokeying est comme la transparence, il permet de définir une codés en dur couleur que le masque de couleur (ou seuil alpha pour mélange keying), ce qui permet d'arrière-plan pour être vu à travers des portions de premier plan qui possèdent cette couleur.

Si votre format d'image prend en charge le type de données ou pixelformat pour les valeurs alpha, il est assez trivial pour calculer:

Alpha basé sur la luminosité = (R + G + B) / 3;

Alpha basé sur le canal presidence = Max(R,G,B);

Mixte de la transparence avec un seuil alpha de 127 signifie que chaque pixel qui a passé le test alpha avec une valeur de 127 ou inférieur serait mélangé, et ceux au-dessus de 127 serait masquée.

J'espère que permet de clarifier un peu, juste au cas où il n'est pas clair. Le code impressionnant les gars.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X