2013-03-16 115 views
0

我已经通过每个资源和不能修复我的问题。OpenCL RGB-> HSL并返回

我的主机代码调用rgb2hsl内核,然后调用hsl2rgb内核。我应该以与我开始的相同图像结束,但我不这样做。我的新图像色调在某些区域已关闭。

红色区域不应该在那里。 这里是发生了什么的屏幕截图:

enter image description here

这里是原始图片

enter image description here

这里是代码:

#define E .0000001f 

bool fEqual(float x, float y) 
{ 
    return (x+E > y && x-E < y); 
} 

__kernel void rgb2hsl(__global float *values, int numValues) 
{ 
    // thread index and total 
    int idx = get_global_id(0); 
    int idxVec3 = idx*3; 
    float3 gMem; 
    if (idx < numValues) 
    { 
     gMem.x = values[idxVec3]; 
     gMem.y = values[idxVec3+1]; 
     gMem.z = values[idxVec3+2]; 
    } 

    barrier(CLK_LOCAL_MEM_FENCE); 

    gMem /= 255.0f; //convert from 256 color to float 

    //calculate chroma 
    float M = max(gMem.x, gMem.y); 
    M = max(M, gMem.z); 
    float m = min(gMem.x, gMem.y); 
    m = min(m, gMem.z); 
    float chroma = M-m; //calculate chroma 
    float lightness = (M+m)/2.0f; 
    float saturation = chroma/(1.0f-fabs(2.0f*lightness-1.0f)); 

    float hue = 0; 
    if (fEqual(gMem.x, M)) 
     hue = (int)((gMem.y - gMem.z)/chroma) % 6; 
    if (fEqual(gMem.y, M)) 
     hue = (((gMem.z - gMem.x))/chroma) + 2; 
    if (fEqual(gMem.z, M)) 
     hue = (((gMem.x - gMem.y))/chroma) + 4; 
    hue *= 60.0f; 


    barrier(CLK_LOCAL_MEM_FENCE); 

    if (idx < numValues) 
    { 
     values[idxVec3] = hue; 
     values[idxVec3+1] = saturation; 
     values[idxVec3+2] = lightness; 
    } 
} 

__kernel void hsl2rgb(__global float *values, int numValues) 
{ 
    // thread index and total 
    int idx = get_global_id(0); 
    int idxVec3 = idx*3; 
    float3 gMem; 
    if (idx < numValues) 
    { 
     gMem.x = values[idxVec3]; 
     gMem.y = values[idxVec3+1]; 
     gMem.z = values[idxVec3+2]; 
    } 

    barrier(CLK_LOCAL_MEM_FENCE); 

    float3 rgb = (float3)(0,0,0); 

    //calculate chroma 
    float chroma = (1.0f - fabs((float)(2.0f*gMem.z - 1.0f))) * gMem.y; 
    float H = gMem.x/60.0f; 
    float x = chroma * (1.0f - fabs(fmod(H, 2.0f) - 1.0f)); 

    switch((int)H) 
    { 
     case 0: 
      rgb = (float3)(chroma, x, 0); 
      break; 
     case 1: 
      rgb = (float3)(x, chroma, 0); 
      break; 
     case 2: 
      rgb = (float3)(0, chroma, x); 
      break; 
     case 3: 
      rgb = (float3)(0, x, chroma); 
      break; 
     case 4: 
      rgb = (float3)(x, 0, chroma); 
      break; 
     case 5: 
      rgb = (float3)(chroma, 0, x); 
      break; 
     default: 
      rgb = (float3)(0, 0, 0);  
    } 

    barrier(CLK_LOCAL_MEM_FENCE); 

    rgb += gMem.z - .5f*chroma; 
    rgb *= 255; 

    if (idx < numValues) 
    { 
     values[idxVec3] = rgb.x; 
     values[idxVec3+1] = rgb.y; 
     values[idxVec3+2] = rgb.z; 
    } 
} 
+0

去除CUDA标签 – 2013-03-16 15:51:56

回答

2

问题是这条线:

hue =(int)((gMem.y - gMem.z)/ chroma)%6;

它应该是 hue = fmod((gMem.y - gMem.z)/ chroma,6.0f);

我做了一些更多的变化,除去工件:

#define E .0000001f 

bool fEqual(float x, float y) 
{ 
    return (x+E > y && x-E < y); 
} 

__kernel void rgb2hsl(__global float *values, int numValues) 
{ 
    // thread index and total 
    int idx = get_global_id(0); 
    int idxVec3 = idx*3; 
    float3 gMem; 
    if (idx < numValues) 
    { 
     gMem.x = values[idxVec3]; 
     gMem.y = values[idxVec3+1]; 
     gMem.z = values[idxVec3+2]; 
    } 

    barrier(CLK_LOCAL_MEM_FENCE); 

    gMem /= 255.0f; //convert from 256 color to float 

    //calculate chroma 
    float M = max(gMem.x, gMem.y); 
    M = max(M, gMem.z); 
    float m = min(gMem.x, gMem.y); 
    m = min(m, gMem.z); 
    float chroma = M-m; //calculate chroma 
    float lightness = (M+m)/2.0f; 
    float saturation = chroma/(1.0f-fabs(2.0f*lightness-1.0f)); 

    float hue = 0; 
    if (fEqual(gMem.x, M)) 
     hue = fmod((gMem.y - gMem.z)/chroma, 6.0f); 
    if (fEqual(gMem.y, M)) 
     hue = (((gMem.z - gMem.x))/chroma) + 2; 
    if (fEqual(gMem.z, M)) 
     hue = (((gMem.x - gMem.y))/chroma) + 4; 
    hue *= 60.0f; 

    barrier(CLK_LOCAL_MEM_FENCE); 

    if (M == m) 
     hue = saturation = 0; 

    barrier(CLK_GLOBAL_MEM_FENCE); 

    if (idx < numValues) 
    { 
     //NOTE: ARTIFACTS SHOW UP if we do not cast to integer! 
     values[idxVec3] = (int)hue; 
     values[idxVec3+1] = saturation; 
     values[idxVec3+2] = lightness; 
    } 
}