与 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 值。
我正在查看 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 值。