OpenCL油画

时间:2017-06-05 21:19:10

标签: opencl

我想在OpenCL中实现油画滤镜,但输出图像总是黑色的,我无法弄清楚原因。 这是内核代码:

__kernel void oil_painting(__global const char* R,__global const char* G,__global const char* B,
                 __global char* r,__global char* g,__global char* b)
{
    int i=get_global_id(0);
    int j=get_global_id(1);
    int i1,j1,k;

    int avgR[256],avgG[256],avgB[256],intensity_count[256];
    int max_pixels=0,max_intensity=0,current_intensity;

    for (i1=0;i1<4;i1++) {
        for (j1=0;j1<4;j1++) {
            current_intensity=(((R[(i+i1)*512+j+j1]+
                                 G[(i+i1)*512+j+j1]+
                                 B[(i+i1)*512+j+j1])/3)*70)/255;
            intensity_count[current_intensity]++;

            if (intensity_count[current_intensity]>max_pixels) {
                max_pixels=intensity_count[current_intensity];
                max_intensity=current_intensity;
            }

            avgR[current_intensity]+=R[(i+i1)*512+j+j1];
            avgG[current_intensity]+=G[(i+i1)*512+j+j1];
            avgB[current_intensity]+=B[(i+i1)*512+j+j1];
        }
    }

    r[i*512+j]=min(255,max(0,avgR[max_intensity]/max_pixels));
    g[i*512+j]=min(255,max(0,avgG[max_intensity]/max_pixels));
    b[i*512+j]=min(255,max(0,avgB[max_intensity]/max_pixels));
}

1 个答案:

答案 0 :(得分:2)

以下代码片段会让您遇到很多麻烦:

current_intensity=(((R[(i+i1)*512+j+j1]+
                     G[(i+i1)*512+j+j1]+
                     B[(i+i1)*512+j+j1])/3)*70)/255;

考虑对于&lt; 127,127,127&gt;的像素会发生什么:

127 + 127 + 127 = 125 (truncated because `char` is only 8 bytes...)
125 / 3 = 41
41 * 70 = 54 (truncated because `char` is only 8 bytes...)
54 / 255 = 0 (this will always equal 0!)

所以intensity_count只会增加其第0个索引,而不会增加任何其他内容。

将所有内容投射到int可能会解决此问题。

current_intensity=((((int)R[(i+i1)*512+j+j1]+
                     (int)G[(i+i1)*512+j+j1]+
                     (int)B[(i+i1)*512+j+j1])/3)*70)/255;

新输出:

127 + 127 + 127 = 381
381 / 3 = 127
127 * 70 = 8890
8890 / 255 = 34

但是你现在遇到了一个新问题:如果值高于127怎么办?假设我们将其更改为使用&lt; 200,200,200&gt;代替?

-56 + -56 + -56 = -168 (`char` only has a range in [-128, 127]! You're overflowing!)
-168 / 3 = -56
-56 * 70 = -3920
-3920 / 255 = -15

现在您已经崩溃了,因为您要么尝试访问索引-15,这是非法的,要么您将尝试访问索引{{ 1}},这仍然是非法的。无论哪种方式,你都会得到不好的结果。

最简单的解决方案是将内核参数更改为2^64 - 15 - 1而不是global uchar *,然后确保将任何和所有算法向上转换为global char *int确保不会发生溢出。