【问题标题】:How do I blur a UIImage, but preserve sharp object boundaries?如何模糊 UIImage,但保留清晰的对象边界?
【发布时间】:2013-01-22 10:18:30
【问题描述】:

我想对 UIImage 执行“智能”模糊,其中内容模糊,但边缘仍然清晰。

例如,这是我的原图:

这是应用此模糊后我希望看到的内容:

如何在 UIImage 上进行这样的“智能”模糊?

【问题讨论】:

    标签: iphone ios image-processing uiimage


    【解决方案1】:

    您在此处寻找的模糊称为双边模糊。与标准高斯模糊不同,周围像素颜色与中心像素颜色基于它们与中心像素的相似程度进行平均。这会模糊对象的内部区域,但会保留清晰的轮廓。

    在我的开源 GPUImage 框架中,我有一个过滤器可以执行此操作,称为 GPUImageBilateralFilter。这是应用于图像时的输出(使用 1.0 的 blurSize 和 1.6 的 distanceNormalizationFactor):

    我的结果与您的目标之间存在一些细微差别,但这可能是由于我使用了特定的权重。通过调整此处的参数,您应该能够更接近上述情况。

    OpenCV 也有双边模糊过滤器,如果您想在此框架之外使用它,您可以将源代码带到我的片段着色器并使用它来构建您自己的 OpenGL ES 实现:

     uniform sampler2D inputImageTexture;
    
     const lowp int GAUSSIAN_SAMPLES = 9;
    
     varying highp vec2 textureCoordinate;
     varying highp vec2 blurCoordinates[GAUSSIAN_SAMPLES];
    
     uniform mediump float distanceNormalizationFactor;
    
     void main()
     {
         lowp vec4 centralColor;
         lowp float gaussianWeightTotal;
         lowp vec4 sum;
         lowp vec4 sampleColor;
         lowp float distanceFromCentralColor;
         lowp float gaussianWeight;
    
         centralColor = texture2D(inputImageTexture, blurCoordinates[4]);
         gaussianWeightTotal = 0.18;
         sum = centralColor * 0.18;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[0]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[1]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[2]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[3]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[5]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.15 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[6]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.12 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[7]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.09 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         sampleColor = texture2D(inputImageTexture, blurCoordinates[8]);
         distanceFromCentralColor = min(distance(centralColor, sampleColor) * distanceNormalizationFactor, 1.0);
         gaussianWeight = 0.05 * (1.0 - distanceFromCentralColor);
         gaussianWeightTotal += gaussianWeight;
         sum += sampleColor * gaussianWeight;
    
         gl_FragColor = sum / gaussianWeightTotal;
     }
    

    【讨论】:

    • 很好的答案。喜欢包含一个开源项目和示例代码。
    • @Brad Larson:我可以单独对图像的特定部分应用滤镜效果吗?不适用于整个图像假设我的图像宽度是 320。所以,我想添加从 60 到 70 像素的滤镜效果,然后单独添加 200-220 像素。因此,滤镜效果不适用于整个图像
    • @Brad Larson:+1 谢谢,它很有帮助:D 我已经用它“升级”了一个高斯模糊着色器;我发现效果非常微妙,除非我将原始除数保留在最后一行(未根据与中心颜色的距离进行转换)。不过有一点,虽然边缘更清晰,但它们有点褪色。
    猜你喜欢
    • 2021-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-01
    • 1970-01-01
    • 2011-09-02
    相关资源
    最近更新 更多