UIImageに対して「スマート」ブラーを実行したいのですが、コンテンツはブラーされていますが、エッジはシャープのままです。
たとえば、これが私の元の画像です。
そして、このぼかしが適用された後に私が見たいものは次のとおりです。
UIImageでこのような「スマート」ブラーを実行するにはどうすればよいですか?
UIImageに対して「スマート」ブラーを実行したいのですが、コンテンツはブラーされていますが、エッジはシャープのままです。
たとえば、これが私の元の画像です。
そして、このぼかしが適用された後に私が見たいものは次のとおりです。
UIImageでこのような「スマート」ブラーを実行するにはどうすればよいですか?
ここで探しているブラーは、バイラテラルブラーと呼ばれます。標準のガウスぼかしとは異なり、周囲のピクセルの色は、中央のピクセルとの類似度に基づいて、中央のピクセルの色で平均化されます。これにより、オブジェクトの内部領域がぼやけますが、シャープな輪郭は維持されます。
私のオープンソースGPUImageフレームワークには、GPUImageBilateralFilterと呼ばれるこれを行うフィルターがあります。これは、画像に適用した場合の出力です(blurSizeを1.0、distanceNormalizationFactorを1.6を使用)。
私の結果とあなたの目標の間には若干の違いがありますが、それはおそらく私が使用している特定の重み付けによるものです。ここでパラメータを微調整することにより、これを上記に近づけることができるはずです。
OpenCVにはバイラテラルブラーフィルターもあります。このフレームワークの外部で使用する場合は、ソースコードをフラグメントシェーダーに移動し、これを使用して独自のOpenGLES実装を構築できます。
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;
}