用于iOS的Luma Key(从图像创buildalpha蒙版)
我正在构build一个应用程序,允许用户将自己的图片上传到白色背景上,该应用程序将创build该人物的轮廓。
我很难找出背景。 我正在使用GPUImage
框架,而GPUImageChromaKeyBlendFilter
对于颜色非常适用,但是如果您使用白色/黑色,则很难将这些颜色中的一种颜色键入。 如果我把键设置为白色或黑色,它们的键都是一样的。
有什么build议?
有一个原因,为什么通常蓝色或绿色的屏幕用于电影制作色度键控,而不是白色。 在照片中,任何东西都可以是白色或足够接近白色,尤其是眼睛或高光或皮肤的一部分。 而且,find一个没有阴影的统一的白色墙壁是很难find的。 我会build议build立一个直方图,find最亮的最常用的颜色,然后使用一些阈值search该颜色的最大面积。 然后从该区域进行洪水填充,直到遇到足够不同的颜色。 除非需要实时videostream,否则所有这些都可以用软件轻松完成。
所以,要将白色变为透明,我们可以使用这个方法:
-(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; }
并用黑色取代不透明像素,我们可以使用:
- (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; }
所以在实践中这将是:
-(UIImage *)silhouetteForImage:(UIImage *)img { return [self changeColour:[self changeWhiteColorTransparent:img]]; }
显然你会在后台线程中调用这个函数,以保证一切运行顺利。
玩Quartzcomposer php和CoreImagefilter可以帮助你。 我相信这段代码会让你变成一个剪影:
- (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; }
有时澄清你想要达到的目标,然后理解差异可能会有所帮助。 你在谈论我从透明度和透明度两个方面收集的内容。
半透明度考虑了alpha,允许背景根据图像像素的alpha值和背景缓冲区上执行的评估types与前景混合。
透明度允许在具有硬alpha和阈值的部分中将图像“掩蔽”出来,并允许通过掩模看到背景而不混合。 阈值允许基于直到阈值的α值进行有限的混合。
Chromokeying就像透明度,因为它允许您设置一个硬编码的颜色作为蒙版颜色(或混合键控的Alpha阈值),这样可以通过具有该颜色的前景部分看到背景。
如果您的图像格式支持alpha值的数据types或像素格式,则计算相当简单:
基于光度的Alpha =(R + G + B)/ 3;
基于频道主持人的Alpha = Max(R,G,B);
混合的透明度与阿尔法阈值127将意味着通过阿尔法testing的值为127或更低的每个像素将被混合,并且那些高于127的将被硬掩码。
我希望有助于澄清一点,以防万一不清楚。 真棒代码的人。