如何使用 OpenCL 将位图转换为纯黑白
How can I convert a bitmap to pure black and white with OpenCL
我有一个 WPF - C# 项目,我正试图加快我在其中进行的图像处理;通过使用 OpenCL 和 Cloo 来实现。
我确实设法让内核工作,可以将位图更改为灰度,但出于某种原因,我制作的黑白内核只能输出全黑图像。
这是我的内核 .cl
代码:
kernel void ConvertToBlackAndWhite(read_only image2d_t sourceImage, write_only image2d_t outputImage, float threshold)
{
const sampler_t mainSampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
int2 position = (int2)(get_global_id(0), get_global_id(1));
float4 pixel = read_imagef(sourceImage, mainSampler, position);
float grayValue = (0.299 * pixel.z) + (0.587 * pixel.y) + (0.114 * pixel.x); // Get Grayscale Value
const float thresholdValue = threshold * 255.0;
if (grayValue > thresholdValue)
{
const float4 white = (float4){ 255.0, 255.0, 255.0, 255.0 }; // #FFFFFF
write_imagef(outputImage, position, white);
}
else
{
const float4 black = (float4){ 0.0, 0.0, 0.0, 255.0 }; // #000000
write_imagef(outputImage, position, black);
}
}
我哪里错了?
如有任何帮助或提示,我们将不胜感激。
我已经根据@ProjectPhysX 的有用建议更新了我的内核代码:
kernel void ConvertToBlackAndWhite(read_only image2d_t sourceImage, write_only image2d_t outputImage, float threshold)
{
const sampler_t mainSampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
int2 position = (int2)(get_global_id(0), get_global_id(1));
float4 pixel = read_imagef(sourceImage, mainSampler, position);
float grayValue = (0.299f * pixel.z) + (0.587f * pixel.y) + (0.114f * pixel.x); // Get Grayscale Value
if (grayValue > threshold)
{
const float4 white = (float4){ 1.0f, 1.0f, 1.0f, 1.0f }; // #FFFFFF
write_imagef(outputImage, position, white);
}
else
{
const float4 black = (float4){ 0.0f, 0.0f, 0.0f, 1.0f }; // #000000
write_imagef(outputImage, position, black);
}
}
这是将图像添加到 OpenCL 图像内存缓冲区的 C#:
...
// Allocate OpenCL Image Memory Buffer
inputImage2DBuffer = Cl.CreateImage2D(GPUManipulation.OpenCLContext, MemFlags.CopyHostPtr | MemFlags.ReadOnly, imageFormat,
(IntPtr)width, (IntPtr)height,
(IntPtr)ConstantsMain.Int0, inputByteArray, out error);
...
// Allocate OpenCL image memory buffer
IMem outputImage2DBuffer = Cl.CreateImage2D(GPUManipulation.OpenCLContext, MemFlags.CopyHostPtr | MemFlags.WriteOnly, imageFormat,
(IntPtr)width, (IntPtr)height, (IntPtr)ConstantsMain.Int0, outputByteArray, out error);
...
read_imagef
returns color/alpha 范围内的值 [0.0f, 1.0f]
而不是 [0.0f, 255.0f]
。这意味着您必须设置:
const float thresholdValue = threshold; // do not multiply by 255.0f here
const float4 white = (float4){ 1.0f, 1.0f, 1.0f, 1.0f }; // #FFFFFF
const float4 black = (float4){ 0.0f, 0.0f, 0.0f, 1.0f }; // #000000
之前全黑的原因是没有grayValue
(在[0.0f, 1.0f]
范围内)可能大于thresholdValue
(在0.5f*255.0f
的顺序) .
我有一个 WPF - C# 项目,我正试图加快我在其中进行的图像处理;通过使用 OpenCL 和 Cloo 来实现。
我确实设法让内核工作,可以将位图更改为灰度,但出于某种原因,我制作的黑白内核只能输出全黑图像。
这是我的内核 .cl
代码:
kernel void ConvertToBlackAndWhite(read_only image2d_t sourceImage, write_only image2d_t outputImage, float threshold)
{
const sampler_t mainSampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
int2 position = (int2)(get_global_id(0), get_global_id(1));
float4 pixel = read_imagef(sourceImage, mainSampler, position);
float grayValue = (0.299 * pixel.z) + (0.587 * pixel.y) + (0.114 * pixel.x); // Get Grayscale Value
const float thresholdValue = threshold * 255.0;
if (grayValue > thresholdValue)
{
const float4 white = (float4){ 255.0, 255.0, 255.0, 255.0 }; // #FFFFFF
write_imagef(outputImage, position, white);
}
else
{
const float4 black = (float4){ 0.0, 0.0, 0.0, 255.0 }; // #000000
write_imagef(outputImage, position, black);
}
}
我哪里错了?
如有任何帮助或提示,我们将不胜感激。
我已经根据@ProjectPhysX 的有用建议更新了我的内核代码:
kernel void ConvertToBlackAndWhite(read_only image2d_t sourceImage, write_only image2d_t outputImage, float threshold)
{
const sampler_t mainSampler = CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_LINEAR;
int2 position = (int2)(get_global_id(0), get_global_id(1));
float4 pixel = read_imagef(sourceImage, mainSampler, position);
float grayValue = (0.299f * pixel.z) + (0.587f * pixel.y) + (0.114f * pixel.x); // Get Grayscale Value
if (grayValue > threshold)
{
const float4 white = (float4){ 1.0f, 1.0f, 1.0f, 1.0f }; // #FFFFFF
write_imagef(outputImage, position, white);
}
else
{
const float4 black = (float4){ 0.0f, 0.0f, 0.0f, 1.0f }; // #000000
write_imagef(outputImage, position, black);
}
}
这是将图像添加到 OpenCL 图像内存缓冲区的 C#:
...
// Allocate OpenCL Image Memory Buffer
inputImage2DBuffer = Cl.CreateImage2D(GPUManipulation.OpenCLContext, MemFlags.CopyHostPtr | MemFlags.ReadOnly, imageFormat,
(IntPtr)width, (IntPtr)height,
(IntPtr)ConstantsMain.Int0, inputByteArray, out error);
...
// Allocate OpenCL image memory buffer
IMem outputImage2DBuffer = Cl.CreateImage2D(GPUManipulation.OpenCLContext, MemFlags.CopyHostPtr | MemFlags.WriteOnly, imageFormat,
(IntPtr)width, (IntPtr)height, (IntPtr)ConstantsMain.Int0, outputByteArray, out error);
...
read_imagef
returns color/alpha 范围内的值 [0.0f, 1.0f]
而不是 [0.0f, 255.0f]
。这意味着您必须设置:
const float thresholdValue = threshold; // do not multiply by 255.0f here
const float4 white = (float4){ 1.0f, 1.0f, 1.0f, 1.0f }; // #FFFFFF
const float4 black = (float4){ 0.0f, 0.0f, 0.0f, 1.0f }; // #000000
之前全黑的原因是没有grayValue
(在[0.0f, 1.0f]
范围内)可能大于thresholdValue
(在0.5f*255.0f
的顺序) .