iOS 5是否支持模糊CoreImage过滤器?

时间:2011-12-16 01:14:45

标签: cocoa-touch ios5 core-image

根据文档,它应该支持模糊,请注意“在iOS 5.0及更高版本中可用”:

CIFilter Class Reference

但根据该设备,它不会:

[CIFilter filterNamesInCategory:kCICategoryBlur];

什么都不返回。

根据以下内容,我的iPhone和模拟器上只有这些过滤器可用(它们都运行5.0):

[CIFilter filterNamesInCategory:kCICategoryBuiltIn]

CIAdditionCompositing,
CIAffineTransform,
CICheckerboardGenerator,
CIColorBlendMode,
CIColorBurnBlendMode,
CIColorControls,
CIColorCube,
CIColorDodgeBlendMode,
CIColorInvert,
CIColorMatrix,
CIColorMonochrome,
CIConstantColorGenerator,
CICrop,
CIDarkenBlendMode,
CIDifferenceBlendMode,
CIExclusionBlendMode,
CIExposureAdjust,
CIFalseColor,
CIGammaAdjust,
CIGaussianGradient,
CIHardLightBlendMode,
CIHighlightShadowAdjust,
CIHueAdjust,
CIHueBlendMode,
CILightenBlendMode,
CILinearGradient,
CILuminosityBlendMode,
CIMaximumCompositing,
CIMinimumCompositing,
CIMultiplyBlendMode,
CIMultiplyCompositing,
CIOverlayBlendMode,
CIRadialGradient,
CISaturationBlendMode,
CIScreenBlendMode,
CISepiaTone,
CISoftLightBlendMode,
CISourceAtopCompositing,
CISourceInCompositing,
CISourceOutCompositing,
CISourceOverCompositing,
CIStraightenFilter,
CIStripesGenerator,
CITemperatureAndTint,
CIToneCurve,
CIVibrance,
CIVignette,
CIWhitePointAdjust

8 个答案:

答案 0 :(得分:31)

虽然iOS 5.0上的Core Image缺少模糊滤镜,但仍有一种方法可以让GPU加速图像和视频模糊。我的开源GPUImage框架有多种模糊类型,包括Gaussian(使用GPUImageGaussianBlurFilter用于普通Gaussian或GPUImageFastBlurFilter用于硬件优化的9-hit Gaussian),box(使用GPUImageBoxBlurFilter),中位数(使用GPUImageMedianFilter) )和双边模糊(使用GPUImageBilateralBlurFilter)。

我描述了用于在this answer中完成硬件优化高斯模糊的着色器,您可以检查我在框架中使用的其余代码。这些过滤器的运行速度比我尝试的任何CPU绑定程序快几十倍。

我还将这些模糊结合到多阶段处理效果中,例如反锐化掩模,倾斜移位滤波,Canny边缘检测和Harris角点检测,所有这些都可以作为此框架中的过滤器使用。

答案 1 :(得分:25)

再一次,为了保存所有iOS模糊问题,这是我的贡献:

https://github.com/tomsoft1/StackBluriOS

基于Stack Blur的简单模糊库。 Stack Blur与Gaussian Blur非常相似,但更快(参见http://incubator.quasimondo.com/processing/fast_blur_deluxe.php

像这样使用它:

UIImage *newIma=[sourceIma stackBlur:radius]

希望这个帮助

答案 2 :(得分:23)

我也很失望地发现iOS中的Core Image不支持模糊。这是我写的在UIImage上做9抽头高斯模糊的函数。反复调用以获得更强的模糊效果。

@interface UIImage (ImageBlur)
- (UIImage *)imageWithGaussianBlur9;
@end

@implementation UIImage (ImageBlur)
- (UIImage *)imageWithGaussianBlur9 {
    float weight[5] = {0.2270270270, 0.1945945946, 0.1216216216, 0.0540540541, 0.0162162162};
    // Blur horizontally
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [self drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[0]];
    for (int x = 1; x < 5; ++x) {
        [self drawInRect:CGRectMake(x, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[x]];
        [self drawInRect:CGRectMake(-x, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[x]];
    }
    UIImage *horizBlurredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    // Blur vertically
    UIGraphicsBeginImageContextWithOptions(self.size, NO, self.scale);
    [horizBlurredImage drawInRect:CGRectMake(0, 0, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[0]];
    for (int y = 1; y < 5; ++y) {
        [horizBlurredImage drawInRect:CGRectMake(0, y, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[y]];
        [horizBlurredImage drawInRect:CGRectMake(0, -y, self.size.width, self.size.height) blendMode:kCGBlendModePlusLighter alpha:weight[y]];
    }
    UIImage *blurredImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    //
    return blurredImage;
}

只需在现有图片上调用它:

UIImage *blurredImage = [originalImage imageWithGaussianBlur9];

并重复它以获得更强的模糊效果,如下所示:

blurredImage = [blurredImage imageWithGaussianBlur9];

答案 3 :(得分:5)

不幸的是,它不支持任何模糊。为此,你必须自己动手。

答案 4 :(得分:4)

更新:从iOS 6开始[CIFilter filterNamesInCategory:kCICategoryBlur];返回CIGaussianBlur,表示此过滤器在设备上可用。即使这是真的,您(可能)将使用GPUImage获得更好的性能和更大的灵活性。

答案 5 :(得分:1)

以下是我们关于在iOS应用程序中使用不同方法制作模糊效果的教程的链接。 http://blog.denivip.ru/index.php/2013/01/blur-effect-in-ios-applications/?lang=en

答案 6 :(得分:0)

如果你可以在你的iOS应用程序中使用OpenGL ES,这就是你如何计算你选择的像素邻域半径的​​中位数(中位数是一种模糊,当然):

kernel vec4 medianUnsharpKernel(sampler u) {
vec4 pixel = unpremultiply(sample(u, samplerCoord(u)));
vec2 xy = destCoord();
int radius = 3;
int bounds = (radius - 1) / 2;
vec4 sum  = vec4(0.0);
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        sum += unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
    }
}
vec4 mean = vec4(sum / vec4(pow(float(radius), 2.0)));
float mean_avg = float(mean);
float comp_avg = 0.0;
vec4 comp  = vec4(0.0);
vec4 median  = mean;
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        comp = unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
        comp_avg = float(comp);
        median = (comp_avg < mean_avg) ? max(median, comp) : median;
    }
}

return premultiply(vec4(vec3(abs(pixel.rgb - median.rgb)), 1.0)); 
}

步骤的简要说明 1.计算3x3邻域中源像素周围的像素值的平均值; 2.找到同一邻域中小于均值的所有像素的最大像素值。 3. [可选]从源像素值中减去中值像素值以进行边缘检测。

如果您使用中值进行边缘检测,有几种方法可以修改上述代码以获得更好的结果,即混合中值滤波和截断媒体滤波(替代品和更好的&#39) ;模式&#39;过滤)。如果您有兴趣,请询问。

答案 7 :(得分:0)

因为我使用的是Xamarin,所以我将John Stephen的答案转换为C#:

    private UIImage ImageWithGaussianBlur9(UIImage image)
    {
        var weight = new nfloat[]
        {
            0.2270270270f, 0.1945945946f, 0.1216216216f, 0.0540540541f, 0.0162162162f
        };

        var width = image.Size.Width;
        var height = image.Size.Height;
        // Blur horizontally
        UIGraphics.BeginImageContextWithOptions(image.Size, false, 1f);

        image.Draw(new CGRect(0f, 0f, width, height), CGBlendMode.PlusLighter, weight[0]);

        for (int x = 1; x < 5; ++x)
        {
            image.Draw(new CGRect(x, 0, width, height), CGBlendMode.PlusLighter, weight[x]);
            image.Draw(new CGRect(-x, 0, width, height), CGBlendMode.PlusLighter, weight[x]);
        }

        var horizBlurredImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        // Blur vertically
        UIGraphics.BeginImageContextWithOptions(image.Size, false, 1f);

        horizBlurredImage.Draw(new CGRect(0, 0, width, height), CGBlendMode.PlusLighter, weight[0]);

        for (int y = 1; y < 5; ++y)
        {
            horizBlurredImage.Draw(new CGRect(0, y, width, height), CGBlendMode.PlusLighter, weight[y]);
            horizBlurredImage.Draw(new CGRect(0, -y, width, height), CGBlendMode.PlusLighter, weight[y]);
        }

        var blurredImage = UIGraphics.GetImageFromCurrentImageContext();
        UIGraphics.EndImageContext();

        return blurredImage;
    }