1

嗨 GPUImage 社区和布拉德,

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

指定 GPU 的需求是否值得称赞?还是可以通过 GPUImage 包装器来完成?如果是这样,我该怎么做?

谢谢

4

2 回答 2

6

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

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

GPUImageGaussianBlurFilter 在两个单独的通道中进行 9-hit 简单高斯模糊。blurSize 属性允许您稍微扩大或缩小采样区域,但如果超过 1.5 的乘数,您将开始看到边缘伪影,因为用于模糊大区域的样本太少。我正在研究几种以高性能方式扩展模糊区域的方法,但这是这个特定过滤器的限制。

于 2012-06-23T15:45:53.310 回答
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. [可选] 从源像素值中减去中间像素值进行边缘检测。

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

于 2015-07-04T00:20:22.513 回答