以下是我的
grayscale.cl
内核实现。我面临的问题是内核似乎仅在第一个像素上执行灰度计算,并通过迭代将该值分配给所有其他像素。
我是否正确使用了 read_imagef
和
write_imagef
?grayscale.cl
__kernel void grayscale(
__read_only image2d_t inputImage,
__write_only image2d_t outputImage,
const int width,
const int height)
{
int x = get_global_id(0); // X-coordinate
int y = get_global_id(1); // Y-coordinate
if (x < get_image_width(inputImage) && y < get_image_height(inputImage)) {
int2 coord = (int2)(x, y);
float4 pixel = read_imagef(inputImage, CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST, coord);
// Converts un-normalised values
float f_x = pixel.x * 255.0f;
float f_y = pixel.y * 255.0f;
float f_z = pixel.z * 255.0f;
printf("Processing pixel: (%d, %d) : %f, %f, %f\n", x, y, f_x, f_y, f_z);
// Grayscale calculation
float gray = 0.299f * f_x + 0.587f * f_y + 0.114f * f_z;
// Write the grayscale value to the output image
write_imagef(outputImage, coord, (float4)(gray, gray, gray, 1.0f));
}
}
内核调试输出
Processing pixel: (292, 233) : 23.000000, 5.000000, 3.000000
Processing pixel: (293, 233) : 23.000000, 5.000000, 3.000000
Processing pixel: (294, 233) : 23.000000, 5.000000, 3.000000
Processing pixel: (295, 233) : 23.000000, 5.000000, 3.000000
以下是上下文的相应(汇总)主机代码。
使用 OpenCV 获取图像
// Load the input image using OpenCV
cv::Mat image = cv::imread(image_path, cv::IMREAD_COLOR);
if(image.empty()){
logger.log("Failed to load image", Logger::LogLevel::ERROR);
}
// Display image (if necessary)
if(DISPLAY_IMAGES){
cv::imshow("Reference Image Window", image);
cv::waitKey(0);
}
// Convert to RGBA and get image dimensions
cv::cvtColor(image, image, cv::COLOR_BGR2RGBA);
*width = image.cols;
*height = image.rows;
// Flatten image into uchar array
std::vector<unsigned char> _input_data(image.data, image.data + image.total() * 4);
图像对象
// Define cl_image variables and format
cl_image_format input_format;
input_format.image_channel_order = CL_RGBA; // RGB
input_format.image_channel_data_type = CL_UNORM_INT8;
cl_image_format output_format;
output_format.image_channel_order = CL_R; // Single channel (grayscale)
output_format.image_channel_data_type = CL_FLOAT;
// Create memory objects
cl_mem input_image = clCreateImage2D(*context, CL_MEM_READ_ONLY | CL_MEM_COPY_HOST_PTR, &input_format, width, height, 0, input_data.data(), &err_num);
if(err_num != CL_SUCCESS){
logger.log("Failed to create cl_image input_image mem object", Logger::LogLevel::ERROR);
}
cl_mem output_image = clCreateImage2D(*context, CL_MEM_WRITE_ONLY, &output_format, width, height, 0, nullptr, &err_num);
if(err_num != CL_SUCCESS){
logger.log("Failed to create cl_image output_image mem object", Logger::LogLevel::ERROR);
}
内核:写入、执行和读取
// Initialise input image
size_t origin[3] = {0, 0, 0};
size_t region[3] = {width, height, 1};
// Set kernel arguments
err_num = clSetKernelArg(*kernel, 0, sizeof(cl_mem), &input_image);
err_num |= clSetKernelArg(*kernel, 1, sizeof(cl_mem), &output_image);
err_num |= clSetKernelArg(*kernel, 2, sizeof(int), &width);
err_num |= clSetKernelArg(*kernel, 3, sizeof(int), &height);
if(err_num != CL_SUCCESS){
logger.log("Failed to set kernel arguments", Logger::LogLevel::ERROR);
}
err_num = clEnqueueWriteImage(*command_queue, input_image, CL_TRUE, origin, region, 0, 0, input_data.data(), 0, nullptr, &write_event);
if(err_num != CL_SUCCESS){
logger.log("Failed to write cl_image", Logger::LogLevel::ERROR);
}
// Perform kernel
err_num = clEnqueueNDRangeKernel(*command_queue, *kernel, 2, nullptr, global_work_size, nullptr, 0, nullptr, &kernel_event);
if(err_num != CL_SUCCESS){
logger.log("Failed when executing kernel", Logger::LogLevel::ERROR);
}
// Read back image data
err_num = clEnqueueReadImage(*command_queue, output_image, CL_TRUE, origin, region, 0, 0, output_data.data(), 0, nullptr, &read_event);
if(err_num != CL_SUCCESS){
logger.log("Failed to read back image data from kernel", Logger::LogLevel::ERROR);
}
我是 OpenCL 新手,因此我们将不胜感激。
提前致谢!