0

私はすべてのリソースを調べましたが、問題を解決できません。

私のホスト コードは rgb2hsl カーネルを呼び出し、次に hsl2rgb カーネルを呼び出します。最初と同じイメージで終わるはずですが、そうではありません。新しい画像の色合いが特定の領域でずれています。

赤い領域があってはなりません。何が起こるかのスクリーンショットは次のとおりです。

ここに画像の説明を入力

これが元の写真です

ここに画像の説明を入力

コードは次のとおりです。

#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;
    }
}
4

1 に答える 1

2

問題は次の行でした。

色相 = (int)((gMem.y - gMem.z)/クロマ) % 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;
    }
}
于 2013-03-17T17:46:34.563 に答える