Anonymous
OpenCL: ядро читает только первый пиксель
Сообщение
Anonymous » 16 дек 2024, 01:07
Ядро оттенков серого читает только первый пиксель
Ниже представлена моя реализация ядра Grayscale.cl. Проблема, с которой я столкнулся, заключается в том, что ядро, похоже, выполняет расчет оттенков серого
только для первого пикселя и присваивает это значение всем остальным пикселям во время итерации.
Правильно ли я использую read_imagef и write_imagef?
Код: Выделить всё
__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 _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, поэтому буду очень признателен за любую помощь.
Заранее спасибо!
Подробнее здесь:
https://stackoverflow.com/questions/792 ... irst-pixel
1734300452
Anonymous
Ядро оттенков серого читает только первый пиксель Ниже представлена моя реализация ядра Grayscale.cl. Проблема, с которой я столкнулся, заключается в том, что ядро, похоже, выполняет расчет оттенков серого [b]только[/b] для первого пикселя и присваивает это значение всем остальным пикселям во время итерации. Правильно ли я использую read_imagef и write_imagef? [code]grayscale.cl[/code] [code]__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)); } } [/code] Вывод отладки ядра [code]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 [/code] Ниже приведен соответствующий (обобщенный) код хоста для контекста. Получение изображения с использованием OpenCV [code]// 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 _input_data(image.data, image.data + image.total() * 4); [/code] Объекты изображений [code]// 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); } [/code] Ядро: запись, выполнение и чтение [code]// 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); } [/code] Я новичок в OpenCL, поэтому буду очень признателен за любую помощь. Заранее спасибо! Подробнее здесь: [url]https://stackoverflow.com/questions/79283239/opencl-kernel-only-reading-first-pixel[/url]