我正在构建一个应用程序,允许人们在白色背景上上传自己的图像,该应用程序将创建一个人的轮廓。
我很难找出背景。我正在使用GPUImage
框架,GPUImageChromaKeyBlendFilter
非常适合颜色,但是如果你使用白色/黑色,很难找出其中一种颜色。如果我将键设置为白色或黑色,则键入相同的键。
有什么建议吗?
答案 0 :(得分:1)
通常在电影制作中使用蓝色或绿色屏幕进行色度键控而不是白色,这是有原因的。照片中任何东西都可以是白色或足够接近白色,尤其是眼睛或高光或仅仅是皮肤的一部分。此外,很难找到一个没有阴影的均匀白墙,至少由你的主题投射。 我建议建立一个直方图,在最亮的颜色中找到最常用的颜色,然后使用一些阈值搜索该颜色的最大区域。然后从该区域进行洪水填充,直到遇到足够不同的颜色。除非您需要实时视频流,否则所有这一切都可以在软件中轻松完成。
答案 1 :(得分:0)
因此,要将白色更改为透明,我们可以使用此方法:
-(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]];
}
显然你会在后台线程中调用它,以保证一切顺利运行。
答案 2 :(得分:0)
使用Quartz编辑器和CoreImage过滤器可能会对您有所帮助。我相信这段代码可以让你成为一个剪影:
- (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;
}
答案 3 :(得分:0)
有时澄清你想要达到的目标然后理解差异可能有所帮助。你所谈论的是我对半透明与透明度的关系。
半透明考虑了alpha,允许根据图像像素的alpha值和在背景缓冲区上执行的评估类型将背景与前景混合。
透明度允许在具有硬alpha和阈值的部分中“遮盖”图像,并允许通过遮罩看到背景而不进行混合。阈值允许基于alpha值的有限混合直到阈值。
Chromokeying就像透明,因为它允许您将硬编码颜色设置为蒙版颜色(或混合键控的alpha阈值),这样可以通过拥有该颜色的前景部分看到背景。
如果您的图像格式支持alpha值的数据类型或pixelformat,那么计算它是非常简单的:
Alpha基于发光度=(R + G + B)/ 3;
基于渠道总部的Alpha = Max(R,G,B);
Alpha阈值为127的混合透明度意味着每个通过alpha测试的像素值为127或更低的像素将被混合,而127以上的像素将被硬屏蔽。
我希望这有助于澄清一点,以防万一不清楚。很棒的代码人。