GPUImage - 如何为GPUImageMedianFilter和GPUImageGaussianBlurFilter指定过滤器大小

时间:2012-06-18 16:05:05

标签: ios gpu gpuimage

您好GPUImage社区和Brad,

我想指定GPUImageMedianFilter的过滤器大小(半径) 和GPUImageGaussianBlurFilter。

是否需要指定GPU表示赞赏?或者可以通过GPUImage包装器完成吗? 如果是这样,我该怎么做?

由于

2 个答案:

答案 0 :(得分:6)

这可能不是提出有关此框架的具体问题的地方,但我可以就此回答您。

GPUImageMedianFilter是一个硬编码的3x3中值滤波器,基于Morgan McGuire在ShaderX6一书中的文章“A Fast,Small-Radius GPU Median Filter”。有关此问题的更多信息,请参见here,包括此更大半径版本。尽管我发现这是最快的实现,但除了最快的iOS设备之外,运行速度仍然非常慢,因此增加采样区域只会进一步降低速度。

GPUImageGaussianBlurFilter在两个单独的传球中执行9次击中的简单高斯模糊。 blurSize属性允许您稍微扩展或收缩采样区域,但如果超过1.5的乘数,您将开始看到由于太少的样本用于模糊大区域的条纹伪像。我正在研究以高效方式扩展模糊区域的几种方法,但这是这个特定过滤器的限制。

答案 1 :(得分:0)

以下是如何计算您选择的像素 - 邻域半径内的中位数:

kernel vec4 medianUnsharpKernel(sampler u) {
vec4 pixel = unpremultiply(sample(u, samplerCoord(u)));
vec2 xy = destCoord();
int radius = 3;
int bounds = (radius - 1) / 2;
vec4 sum  = vec4(0.0);
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        sum += unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
    }
}
vec4 mean = vec4(sum / vec4(pow(float(radius), 2.0)));
float mean_avg = float(mean);
float comp_avg = 0.0;
vec4 comp  = vec4(0.0);
vec4 median  = mean;
for (int i = (0 - bounds); i <= bounds; i++)
{
    for (int j = (0 - bounds); j <= bounds; j++ )
    {
        comp = unpremultiply(sample(u, samplerTransform(u, vec2(xy + vec2(i, j)))));
        comp_avg = float(comp);
        median = (comp_avg < mean_avg) ? max(median, comp) : median;
    }
}

return premultiply(vec4(vec3(abs(pixel.rgb - median.rgb)), 1.0)); 
}

步骤的简要说明 1.计算3x3邻域中源像素周围的像素值的平均值; 2.找到同一邻域中小于均值的所有像素的最大像素值。 3. [可选]从源像素值中减去中值像素值以进行边缘检测。

如果您使用中值进行边缘检测,有几种方法可以修改上述代码以获得更好的结果,即混合中值滤波和截断媒体滤波(替代品和更好的&#39) ;模式&#39;过滤)。如果您有兴趣,请询问。