从图像中删除背景&只采取图像部分保存在iOS中
这是我需要实现的:
- 从相机或图库中获取图像
- 从图像中删除背景并保存
- 背景应该是黑色或白色的
- 还需要随着背景删除阴影
结果示例:
原始图像
结果图像
这是我曾经试过的:
CGFloat colorMasking[6]={222,255,222,255,222,255}; CGImageRef imageRef = CGImageCreateWithMaskingColors([IMG CGImage], colorMasking); UIImage *resultThumbImage = [UIImage imageWithCGImage:imageRef scale:ThumbImage.scale orientation:IMG.imageOrientation];
它在白色背景的唯一的工作。 它不是更有效。 我需要达到什么我已经放在上面的图像确切的结果。
我也提到了一些参考文献:
iOS如何掩盖图像的背景颜色
如何在iPhone应用程序中删除图像的背景?
将拍摄图像的背景颜色从相机更改为白色
有人可以帮助我实现这个目标吗?
任何参考或将不胜感激。
提前致谢。
通常,根据经验,所有其他颜色背景颜色的差异越大,将图像分割成前景和后景就越容易。 在这种情况下,正如@Chris已经build议的那样,可以使用简单的色度键实现。 下面是我在维基百科上描述的密钥的快速实现(它是用C ++编写的,但是将其翻译成Objective-C应该很容易):
/** * @brief Separate foreground from background using simple chroma keying. * * @param imageBGR Image with monochrome background * @param chromaBGR Color of the background (using channel order BGR and range [0, 255]) * @param tInner Inner threshold, color distances below this value will be counted as foreground * @param tOuter Outer threshold, color distances above this value will be counted as background * * @return Mask (0 - background, 255 - foreground, [1, 255] - partially fore- and background) * * Details can be found on [Wikipedia][1]. * * [1]: https://en.wikipedia.org/wiki/Chroma_key#Programming */ cv::Mat1b chromaKey( const cv::Mat3b & imageBGR, cv::Scalar chromaBGR, double tInner, double tOuter ) { // Basic outline: // // 1. Convert the image to YCrCb. // 2. Measure Euclidean distances of color in YCrBr to chroma value. // 3. Categorize pixels: // * color distances below inner threshold count as foreground; mask value = 0 // * color distances above outer threshold count as background; mask value = 255 // * color distances between inner and outer threshold a linearly interpolated; mask value = [0, 255] assert( tInner <= tOuter ); // Convert to YCrCb. assert( ! imageBGR.empty() ); cv::Size imageSize = imageBGR.size(); cv::Mat3b imageYCrCb; cv::cvtColor( imageBGR, imageYCrCb, cv::COLOR_BGR2YCrCb ); cv::Scalar chromaYCrCb = bgr2ycrcb( chromaBGR ); // Convert a single BGR value to YCrCb. // Build the mask. cv::Mat1b mask = cv::Mat1b::zeros( imageSize ); const cv::Vec3d key( chromaYCrCb[ 0 ], chromaYCrCb[ 1 ], chromaYCrCb[ 2 ] ); for ( int y = 0; y < imageSize.height; ++y ) { for ( int x = 0; x < imageSize.width; ++x ) { const cv::Vec3d color( imageYCrCb( y, x )[ 0 ], imageYCrCb( y, x )[ 1 ], imageYCrCb( y, x )[ 2 ] ); double distance = cv::norm( key - color ); if ( distance < tInner ) { // Current pixel is fully part of the background. mask( y, x ) = 0; } else if ( distance > tOuter ) { // Current pixel is fully part of the foreground. mask( y, x ) = 255; } else { // Current pixel is partially part both, fore- and background; interpolate linearly. // Compute the interpolation factor and clip its value to the range [0, 255]. double d1 = distance - tInner; double d2 = tOuter - tInner; uint8_t alpha = static_cast< uint8_t >( 255. * ( d1 / d2 ) ); mask( y, x ) = alpha; } } } return mask; }
一个完整的代码示例可以在这个Github Gist中find。
不幸的是,你的榜样并不坚持这个经验法则。 由于前景和背景仅在强度上有所不同,所以很难(或者甚至不可能)find单个全局参数集来实现良好的分离:
-
物体周围有黑线,物体内没有洞(
tInner=50
,tOuter=90
) -
物体周围没有黑线,但物体内部有孔(
tInner=100
,tOuter=170
)
所以,如果你不能改变你的图像的背景需要一个更复杂的方法。 然而,一个简单而快速的示例实现有点超出范围,但是您可能需要查看图像分割和Alpha Matting的相关领域。
我认为你需要使用色度键 – 尽pipe你select黑色,我认为它应该工作。
一个快速的谷歌提出了这一点
- kCGImageAlphaNone无法parsing的标识符在swift中
- 使用转换CIFilters进行CATransition
- 将核心图像滤镜(CIBumpDistortion)应用于图像的一个部分+改变CIFilter的select和强度的半径
- 用于Core Image的CIGaussianGradientfilter的示例
- 使用GPU(可能CIFilters)将图像放在较大的canvas上,而不使用Image Context
- UIGraphicsBeginImageContext必须是视网膜感知?
- iOS:如何高效地模糊图像?
- CIGaussianBlur和iOS 6上的CIAffineClamp
- 如何使用kciFormatRGBAh获得与Core Image iOS的一半浮动?