CUDA盒式过滤器的工作原理是什么?

时间:2017-07-05 12:47:12

标签: c++ cuda

我有这个代码示例,我试图理解它:

    __global__ void
d_boxfilter_rgba_x(unsigned int *od, int w, int h, int r)
    {
    float scale = 1.0f / (float)((r << 1) + 1);
    unsigned int y = blockIdx.x*blockDim.x + threadIdx.x;

    if (y < h)
        {
        float4 t = make_float4(0.0f);

        for (int x = -r; x <= r; x++)
            {
            t += tex2D(rgbaTex, x, y);
            }

        od[y * w] = rgbaFloatToInt(t * scale);

        for (int x = 1; x < w; x++)
            {
            t += tex2D(rgbaTex, x + r, y);
            t -= tex2D(rgbaTex, x - r - 1, y);
            od[y * w + x] = rgbaFloatToInt(t * scale);
            }
        }
    }

__global__ void
d_boxfilter_rgba_y(unsigned int *id, unsigned int *od, int w, int h, int r)
    {
    unsigned int x = blockIdx.x*blockDim.x + threadIdx.x;
    id = &id[x];
    od = &od[x];

    float scale = 1.0f / (float)((r << 1) + 1);

    float4 t;
    // partea din stanga
    t = rgbaIntToFloat(id[0]) * r;

    for (int y = 0; y < (r + 1); y++)
        {
        t += rgbaIntToFloat(id[y*w]);
        }

    od[0] = rgbaFloatToInt(t * scale);

    for (int y = 1; y < (r + 1); y++)
        {
        t += rgbaIntToFloat(id[(y + r) * w]);
        t -= rgbaIntToFloat(id[0]);
        od[y * w] = rgbaFloatToInt(t * scale);
        }

    // main loop
    for (int y = (r + 1); y < (h - r); y++)
        {
        t += rgbaIntToFloat(id[(y + r) * w]);
        t -= rgbaIntToFloat(id[((y - r) * w) - w]);
        od[y * w] = rgbaFloatToInt(t * scale);
        }

    // right side
    for (int y = h - r; y < h; y++)
        {
        t += rgbaIntToFloat(id[(h - 1) * w]);
        t -= rgbaIntToFloat(id[((y - r) * w) - w]);
        od[y * w] = rgbaFloatToInt(t * scale);
        }
    }

这应该是带有CUDA的盒式过滤器。 根据我的阅读,这应该是给定半径的平均值。 但是在d_boxfilter_rgba_y中做了类似这样的事情:

od[0] = rgbaFloatToInt(t * scale);

我不明白为什么使用这个比例,为什么在应该只有一个时做出所有的循环。要计算从-r到+ r的值并将其除以像素数。

有人能帮助我吗?

1 个答案:

答案 0 :(得分:1)

要计算半径为1(3个值)的方框的平均值,请执行以下操作:

(box[0] + box[1] + box[2]) / 3 // which is equal to
(box[0] + box[1] + box[2] * 1/3 // which is equal to your scale factor

规模的计算是:

1.0f / (float)((r << 1) + 1); // equal to
1 / ((r * 2) + 1) // equal to
1 / (2r + 1) // 2r because you go to the left and right and +1 for the middle

使用了两个for循环,因为&#34;滑动窗口&#34;使用优化。首先计算第一个框:

for (int x = -r; x <= r; x++)
{
    t += tex2D(rgbaTex, x, y);
}

然后对于右侧的每个步骤,添加框的右侧值,并删除框的最左侧值。这样,您只需2次操作即可计算框的总和,而不是2*r + 1次操作。

for (int x = 1; x < w; x++)
{
    t += tex2D(rgbaTex, x + r, y);
    t -= tex2D(rgbaTex, x - r - 1, y);
    od[y * w + x] = rgbaFloatToInt(t * scale);
    }
}