【问题标题】:OpenCL image computing and then screen renderingOpenCL 图像计算然后屏幕渲染
【发布时间】:2016-06-03 20:08:32
【问题描述】:

我不知道如何启动项目来实现这个:

  1. 将 16 位整数矩阵加载到 GPU 内存中(这是灰度放射影像)
  2. 通过应用函数(例如对比度增强算法)从第一个数组计算出第二个 16 位整数矩阵
  3. 第二个矩阵的感兴趣区域被转换为 RGB 图像以在屏幕上显示。

我可以做第一步和第二步,但我被困在了第三步! 我已经在 CPU 中实现了所有这些,所以这不是处理灰度或 RGB 图像的问题,也不是为显示创建位图的问题。 我还在 OpenCL 中实现了前两个步骤,然后在 CPU 内存中读取生成的矩阵以进行 RGB 位图转换,然后显示它。但这当然很慢,因为在 CPU 和 GPU 内存之间来回移动数据(图像非常大:超过 100 兆像素)。

感谢任何帮助。我正在使用 Delphi 10 编程,但 C/C++ 中的示例代码是可以的。我有 VC2010 并成功重建了 NVidia OpenCL oclNbody 示例应用程序。

【问题讨论】:

  • 你尝试过什么没有成功?您可以为灰度源和 RGB 或 RGBA 结果创建 OpenCL 图像,并将它们传递给计算内核。
  • 对于第 3 步,我没有创建任何东西,因为我不知道该怎么做。这就是我实际上要问的。我不知道如何在由 Windows API CreateWindow 创建的窗口中的屏幕上显示 OpenCL (clCreateImage) 中的图像。
  • 我找到了一些非常接近我需要的源代码(amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/… 第 E.1.1 章从 GL 上下文创建 CL 上下文,使用 Win32 API)。不幸的是,对 clGetGLContextInfoKHR 的调用会产生访问冲突,这是由通过属性参数传递给函数的平台变量引起的。我将此源代码移植到 Delphi,这可能是罪魁祸首。如果我有完整的 C 示例程序,我可以在运行时将该 C 版本与我的 Delphi 版本进行比较并了解问题所在。
  • 与访问冲突相关的问题是由对 clGetGLContextInfoKHR 的不当调用引起的:使用 OpenCL 1.2 时(我的情况),功能不同。他的地址必须使用 clGetExtensionFunctionAddressForPlatform 而不是 clGetExtensionFunctionAddress 获得。该版本适用于给定平台,不会导致任何访问冲突。我正在进步……
  • 查看任何有关 OpenCL/OpenGL 互操作的供应商示例,了解在显示器上获取 OpenCL 图像的最佳方式。如果您想改用 GDI,则 clEnqueueReadImage 将其返回到 CPU 内存并使用 GDI 显示(它不会像 OpenGL 那样快,但可能足以满足您的需求)。

标签: delphi opencl


【解决方案1】:

您的问题的解决方案很大程度上取决于您要渲染什么。可能,如果您进行医学图像处理,则需要显示高质量的图像。

根据您的说法,ROI 分辨率比显示器大得多。我不太了解 OpenGL 内置图像缩放过滤器的质量,所以在编写复杂的 OpenCL - OpenGL 互操作代码之前,我首先会测试 OpenGL 是否是一个选项。无论如何,我更喜欢可以自定义的缩放过滤器。

因此,最灵活的选择是创建 2 个大小与显示分辨率相同的 OpenCL 缓冲区。然后,实现 OpenCL 内核,它进行灰度 -> RGB 转换和下采样。

伪代码如下:

// Original grayscale image;
cl_mem orig_image = clCreateBuffer(sizeof(uint16_t)*orig_width*orig_heigth);

// Grayscale ROI, downscaled to dispaly resolution, still 16 bits;
cl_mem disp_grayscale = clCreateBuffer(sizeof(uint16_t)*disp_width*disp_heigth);

// RGB image to display;
cl_mem disp_rgb = clCreateBuffer(sizeof(uint8_t)*3*disp_width*disp_heigth);

clEnqueueNDRangeKernel(DownscaleFilter, orig_image, disp_grayscale);
clEnqueueNDRangeKernel(GrayscaleToRGb, disp_grayscale, disp_rgb);

uint8_t *pixels = clEnqueueMapBuffer(disp_rgb);
// Deal with it as with usual image;

clEnqueueUnmapMemoryObject(disp_rgb);
// pixels are no longer available;

IMO,这里最复杂的问题是开发高质量的降频滤波器。我已经从新的 HEVC 视频编码标准测试了 8 抽头缩小滤波器,效果非常好。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-29
    • 1970-01-01
    • 2013-12-31
    • 1970-01-01
    • 2017-11-15
    • 2012-07-31
    相关资源
    最近更新 更多