与 Int 相比,Opencl Sobel 过滤器实现在 Float 中被淘汰

Opencl Sobel filter implementation washed out in Float compared to Int

我正在查看 3x3 垂直 sobel 的两个实现 filter.One 在浮点数中进行计算,另一个在 long 中进行计算。出于某种原因,浮动版本的边缘在输出中明显被冲掉了。我知道会有一些精度差异,但似乎有很大的差异。

这是长版:

__kernel void sobel(read_only image2d_t inputImage, write_only image2d_t outputImage)
{
    const sampler_t sampler=CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_CLAMP_TO_EDGE|CLK_FILTER_LINEAR;
    int i = get_global_id(0);
    int j = get_global_id(1);
    int accumWeights = 0;
    uint4 pixel_orig=read_imageui(inputImage,sampler,(int2)(i,j));
    long4 pixel_orig_long=convert_long4(pixel_orig);
    long4 pixel_new = (long4)(0, 0, 0, 255);
    long4 pixel0 = convert_long4(read_imageui(inputImage,sampler,(int2)(i+1,j+0)));
    long4 pixel1 = convert_long4(read_imageui(inputImage,sampler,(int2)(i+1,j+1)));
    long4 pixel2 = convert_long4(read_imageui(inputImage,sampler,(int2)(i+1,j-1)));
    long4 pixel3 = convert_long4(read_imageui(inputImage,sampler,(int2)(i-1,j+0)));
    long4 pixel4 = convert_long4(read_imageui(inputImage,sampler,(int2)(i-1,j+1)));
    long4 pixel5 = convert_long4(read_imageui(inputImage,sampler,(int2)(i-1,j-1)));
    pixel_new += (pixel0)*2; 
    pixel_new += (pixel1)*1; 
    pixel_new += (pixel2)*1; 
    pixel_new -= (pixel3)*2; 
    pixel_new -= (pixel4)*1; 
    pixel_new -= (pixel5)*1; 
    if (pixel_new.x<0) pixel_new.x = 0-pixel_new.x; ;
    if (pixel_new.y<0) pixel_new.y = 0-pixel_new.y; ;
    if (pixel_new.z<0) pixel_new.z = 0-pixel_new.z; ;
    pixel_new.w = 255;
    write_imageui(outputImage,(int2)(i,j), convert_uint4(pixel_new));
};

这是浮动版本:

__kernel void sobel(read_only image2d_t inputImage, write_only image2d_t outputImage)
{
    const sampler_t sampler=CLK_NORMALIZED_COORDS_FALSE|CLK_ADDRESS_CLAMP_TO_EDGE|CLK_FILTER_LINEAR;
    int i = get_global_id(0);
    int j = get_global_id(1);
    float4 pixel_orig=read_imagef(inputImage,sampler,(int2)(i,j));
    float4 pixel_new = (float4)(0, 0, 0, 255);
    float4 pixel0 = read_imagef(inputImage,sampler,(int2)(i+1,j+0));
    float4 pixel1 = read_imagef(inputImage,sampler,(int2)(i+1,j+1));
    float4 pixel2 = read_imagef(inputImage,sampler,(int2)(i+1,j-1));
    float4 pixel3 = read_imagef(inputImage,sampler,(int2)(i-1,j+0));
    float4 pixel4 = read_imagef(inputImage,sampler,(int2)(i-1,j+1));
    float4 pixel5 = read_imagef(inputImage,sampler,(int2)(i-1,j-1));
    pixel_new += (pixel0)*2;
    pixel_new += (pixel1)*1;
    pixel_new += (pixel2)*1;
    pixel_new -= (pixel3)*2;
    pixel_new -= (pixel4)*1;
    pixel_new -= (pixel5)*1;
    pixel_new = fabs(pixel_new);
    pixel_new.w = 255;
    write_imagef(outputImage,(int2)(i,j), pixel_new);
};

没有足够的声誉 post 图像,但使用 Lenna 作为测试,边缘的白度在浮动版本中明显被洗掉了。似乎无法弄清楚为什么。

几件事: 1) 您正在使用 CLK_FILTER_LINEAR,但 OpenCL 规范说 "The read_imagef calls that take integer coordinates must use a sampler with filter mode set to CLK_FILTER_NEAREST"。 2) 您正在使用 read_imagef 期望 0-255 但它 returns 规范化 0.0-1.0 值。