我想在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));
}
答案 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
确保不会发生溢出。