2

UIImage でモーション ブラー効果を得る方法はありますか? GPUImage、Filtrr、および iOS Core Image を試しましたが、これらにはすべて通常のブラーがあり、モーション ブラーはありません。

UIImage-DSPも試してみましたが、モーションブラーはほとんど見えません。もっと強いものが必要です。

4

2 に答える 2

6

リポジトリにコメントしたように、モーション ブラーとズーム ブラーを GPUImage に追加しました。これらは GPUImageMotionBlurFilter クラスと GPUImageZoomBlurFilter クラスです。これは、ズーム ブラーの例です。

GPUImage ズームブラー

モーション ブラーでは、単一方向に 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 ヒットのガウス ブラーを使用します。方向とサンプルごとのオフセット距離は、ピクセルの配置とブラーの中心の関数として変化します。

次のフラグメント シェーダー (および標準のパススルー頂点シェーダー) を使用します。

 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 デバイスではテクスチャ サンプリングの帯域幅が限られているため、サンプルを増やすとレンダリング時間が大幅に遅くなります。

于 2013-02-12T19:29:25.483 に答える
0

CoreImage にはモーション ブラー フィルターがあります。

それはCIMotionBlurと呼ばれています... http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Reference/CoreImageFilterReference/Reference/reference.html#//apple_ref/doc/filter/ci/CIMotionBlur

于 2013-02-04T08:19:01.117 に答える