简体   繁体   English

如何模糊UIImage,但保留清晰的对象边界?

[英]How do I blur a UIImage, but preserve sharp object boundaries?

I would like to perform a "smart" blur to a UIImage, where the contents are blurred, but the edges remain sharp. 我想对UIImage进行“智能”模糊处理,其中内容模糊,但边缘保持清晰。

For example, here is my original image: 例如,这是我的原始图片:

清晰的原始图像

and here is what I would like to see after this blur is applied: 这是应用此模糊后我想看到的内容:

影像模糊

How can I do a "smart" blur like this on a UIImage? 如何在UIImage上进行这样的“智能”模糊处理?

The blur you're looking for here is called a bilateral blur. 您在此处查找的模糊称为双边模糊。 Unlike a standard Gaussian blur, surrounding pixel colors are averaged with the center pixel color based on how similar they are to the central pixel. 与标准高斯模糊不同,周围像素颜色是根据与中心像素的相似程度与中心像素颜色进行平均的。 This blurs interior regions of objects, but preserves a sharp outline. 这会模糊对象的内部区域,但保留清晰的轮廓。

In my open source GPUImage framework, I have a filter that does this, called a GPUImageBilateralFilter. 在我的开源GPUImage框架中,我有一个执行此操作的过滤器,称为GPUImageBilateralFilter。 This is the output of that when applied to your image (using a blurSize of 1.0 and a distanceNormalizationFactor of 1.6): 这是应用于图像时的输出(使用blurSize为1.0和distanceNormalizationFactor为1.6):

使用双边模糊过滤橙色

There are some slight differences between my result and your target, but that's probably due to the specific weightings I use. 我的结果和您的目标之间有些细微的差异,但这可能是由于我使用了特定的权重。 By tweaking the parameters here, you should be able to get this closer to the above. 通过在这里调整参数,您应该能够使它更接近于上面。

OpenCV also has bilateral blur filters, and you could take the source code to my fragment shader and use this to construct your own OpenGL ES implementation if you'd like to use it outside of this framework: 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;
 }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM