运动模糊对iOS上UIImage的影响

时间:2013-02-04 07:14:19

标签: ios xcode uiimage

有没有办法在UIImage上获得运动模糊效果? 我尝试过GPUImage,Filtrr和iOS Core Image,但所有这些都有规律的模糊 - 没有运动模糊。

我也尝试过UIImage-DSP,但它的运动模糊几乎不可见。我需要更强大的东西。

2 个答案:

答案 0 :(得分:6)

正如我对存储库的评论,我刚刚将动画和缩放模糊添加到GPUImage。这些是GPUImageMotionBlurFilter和GPUImageZoomBlurFilter类。这是缩放模糊的一个示例:

GPUImage zoom blur

对于运动模糊,我在单个方向上进行9次击中高斯模糊。这是使用以下顶点和片段着色器实现的:

顶点:

 attribute vec4 position;
 attribute vec4 inputTextureCoordinate;

 uniform highp vec2 directionalTexelStep;

 varying vec2 textureCoordinate;
 varying vec2 oneStepBackTextureCoordinate;
 varying vec2 twoStepsBackTextureCoordinate;
 varying vec2 threeStepsBackTextureCoordinate;
 varying vec2 fourStepsBackTextureCoordinate;
 varying vec2 oneStepForwardTextureCoordinate;
 varying vec2 twoStepsForwardTextureCoordinate;
 varying vec2 threeStepsForwardTextureCoordinate;
 varying vec2 fourStepsForwardTextureCoordinate;

 void main()
 {
     gl_Position = position;

     textureCoordinate = inputTextureCoordinate.xy;
     oneStepBackTextureCoordinate = inputTextureCoordinate.xy - directionalTexelStep;
     twoStepsBackTextureCoordinate = inputTextureCoordinate.xy - 2.0 * directionalTexelStep;
     threeStepsBackTextureCoordinate = inputTextureCoordinate.xy - 3.0 * directionalTexelStep;
     fourStepsBackTextureCoordinate = inputTextureCoordinate.xy - 4.0 * directionalTexelStep;
     oneStepForwardTextureCoordinate = inputTextureCoordinate.xy + directionalTexelStep;
     twoStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 2.0 * directionalTexelStep;
     threeStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 3.0 * directionalTexelStep;
     fourStepsForwardTextureCoordinate = inputTextureCoordinate.xy + 4.0 * directionalTexelStep;
 }

片段:

 precision highp float;

 uniform sampler2D inputImageTexture;

 varying vec2 textureCoordinate;
 varying vec2 oneStepBackTextureCoordinate;
 varying vec2 twoStepsBackTextureCoordinate;
 varying vec2 threeStepsBackTextureCoordinate;
 varying vec2 fourStepsBackTextureCoordinate;
 varying vec2 oneStepForwardTextureCoordinate;
 varying vec2 twoStepsForwardTextureCoordinate;
 varying vec2 threeStepsForwardTextureCoordinate;
 varying vec2 fourStepsForwardTextureCoordinate;

 void main()
 {
     lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18;
     fragmentColor += texture2D(inputImageTexture, oneStepBackTextureCoordinate) * 0.15;
     fragmentColor += texture2D(inputImageTexture, twoStepsBackTextureCoordinate) *  0.12;
     fragmentColor += texture2D(inputImageTexture, threeStepsBackTextureCoordinate) * 0.09;
     fragmentColor += texture2D(inputImageTexture, fourStepsBackTextureCoordinate) * 0.05;
     fragmentColor += texture2D(inputImageTexture, oneStepForwardTextureCoordinate) * 0.15;
     fragmentColor += texture2D(inputImageTexture, twoStepsForwardTextureCoordinate) *  0.12;
     fragmentColor += texture2D(inputImageTexture, threeStepsForwardTextureCoordinate) * 0.09;
     fragmentColor += texture2D(inputImageTexture, fourStepsForwardTextureCoordinate) * 0.05;

     gl_FragColor = fragmentColor;
 }

作为优化,我使用角度,模糊大小和图像尺寸计算片段着色器外部的纹理样本之间的步长。然后将其传递到顶点着色器,以便我可以在那里计算纹理采样位置,并在片段着色器中对它们进行插值。这可以避免在iOS设备上进行相关的纹理读取。

变焦模糊要慢得多,因为我仍然在片段着色器中进行这些计算。毫无疑问,有一种方法可以优化它,但我还没有尝试过。变焦模糊使用9次高斯模糊,其中方向和每个样本的偏移距离随着像素的位置与模糊中心的变化而变化。

它使用以下片段着色器(和标准的passthrough顶点着色器):

 varying highp vec2 textureCoordinate;

 uniform sampler2D inputImageTexture;

 uniform highp vec2 blurCenter;
 uniform highp float blurSize;

 void main()
 {
     // TODO: Do a more intelligent scaling based on resolution here
     highp vec2 samplingOffset = 1.0/100.0 * (blurCenter - textureCoordinate) * blurSize;

     lowp vec4 fragmentColor = texture2D(inputImageTexture, textureCoordinate) * 0.18;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate + samplingOffset) * 0.15;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate + (2.0 * samplingOffset)) *  0.12;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate + (3.0 * samplingOffset)) * 0.09;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate + (4.0 * samplingOffset)) * 0.05;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate - samplingOffset) * 0.15;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate - (2.0 * samplingOffset)) *  0.12;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate - (3.0 * samplingOffset)) * 0.09;
     fragmentColor += texture2D(inputImageTexture, textureCoordinate - (4.0 * samplingOffset)) * 0.05;

     gl_FragColor = fragmentColor;
 }

请注意,出于性能原因,这两种模糊都是9个样本的硬编码。这意味着在较大的模糊大小下,您将开始在此处查看有限样本中的工件。对于较大的模糊,您需要多次运行这些滤镜或扩展它们以支持更多高斯样本。但是,由于iOS设备上的纹理采样带宽有限,因此更多样本会导致渲染时间变慢。

答案 1 :(得分:0)