OpenCL:图像处理基础note(转)

使用图像对象的理由

虽然对于图像也可以把它的像素数据当做一般的缓存数据来处理,但是如果把它当做图像来处理有如下好处:

  1. 在GPU中,图像数据是保存在特殊的全局内存中,即纹理内存,它和一般的全局内存不相同,它是被缓存的,用于高速访问处理。GPU中有专门支持图像读写的硬件,使用内置读写函数可以充分发挥这个优势
  2. 只要OpenCL支持该图像格式,那么就可以不用考虑图像格式的前提下使用读写图像数据的函数
  3. 可以使用采样器来配置读取图像中数据的的方式
  4. OpenCL提供函数来获取图像相关信息,比如宽度等

主机与内核的命名

图像相关应用主要涉及两个数据类型,即图像对象采样器。图像对线用来保存主机和设备上的图像对象,而采样器则在设备接收数据时,说明如何读取这些颜色值

 图像对象采样器
主机cl_mem (和一般缓存对象一样)cl_sampler
设备image2d_t或者image3d_tsampler_t

主机编程的主要接口

创建图像对象

cl_mem clCreateImage2D()
cl_mem clCreateImage3D()

图像格式

cl_image_format

创建采样器

cl_sampler clCreateSampler()

设备上的接口

图像数据

由于很多设备都是将图像对象保存在特定的内存中,因此image2d_t以及image3d_t数据的前面通常会有read_only或者write_only等修饰符。图像不能即可写又可读
图像数据作为内核的参数时,和普通的缓存对象不同,它不是指针参数,因为图像数据并不希望直接通过内存操作来访问数据。

采样器

根据khronos官网的说明,采样器其实就是一个uint类型(可以直接给内置cl读写函数传递标识位的组合来替代sampler_t,例如:float4 clr = read_imagef(img, CLK_NORMALIZED_COORDS_FALSE | CLK_ADDRESS_CLAMP_TO_EDGE | CLK_FILTER_NEAREST, (float2)(x, y));),通过bit-mode来说明坐标模式,超出边界的处理模式以及插值模式。在官方的sample中采用的是constant申明的模式,虽然也说了可以采用global声明,但这也许说明constant更好。
可以通过设置参数clSetKernelArg的方式来给内核传递采样器。但是更为方便的方式是在cl文件中,在内核函数之前创建一个sampler_t对象,如下case:

__constant sampler_t sampler = CLK_NORMALIZED_COORDS_FALSE | 
      CLK_ADDRESS_CLAMP | CLK_FILTER_NEAREST;

__kernel void simple_image(read_only image2d_t src_image,
                        write_only image2d_t dst_image) {

  /* Compute value to be subtracted from each pixel */
  uint offset = get_global_id(1) * 0x4000 + get_global_id(0) * 0x1000;

  /* Read pixel value */
  int2 coord = (int2)(get_global_id(0), get_global_id(1));
  uint4 pixel = read_imageui(src_image, sampler, coord);

  /* Subtract offset from pixel */
  pixel.x -= offset;

  /* Write new pixel value to output */
  write_imageui(dst_image, coord, pixel);
}

内置图像函数

OpenCL的内置图像相关的函数主要包括三类:read_imageT读取类,write_imageT写入类以及get_image_X读取图像信息类。其中T表示数据类型,比如f,i,ui等,而X表示width,dim等图像信息

read_image

  • read_image函数返回的都是四分量的数据,如果实际图片没有四个通道的数据,那么那些不含有的的通道对应的分量会被置为0,具体请看官网
  • 很多时候都会看到代码中用float4 read_imagef()去读图像数据为int或者uint类型的image,可能你会困惑为什么整形要用float去读?这是因为,这些图片在创建的时候就是以正则NORM化的数据类型,这个类型在cl_image_formatimage_channel_data_type中指定。以int8为例,image_channel_data_type可取的值如下表:参考
image_channel_data_type 参数含义read_image
CL_SNORM_INT8每个通道都是正则化符号8位整数使用read_imagef读取,返回的float4的每个分量的取值范围为[0.0, 1.0]
CL_UNORM_INT8每个通道都是正则化符号8位整数使用read_imagef读取,返回的float4的每个分量的取值范围为[-1.0, 1.0]
CL_SIGNED_INT8每个通道都是8位有符号的整数使用read_imagei读取,返回int4
CL_USIGNED_INT8每个通道都是8位无符号的整数使用read_imageui读取,返回unsigned int4
  • 使用read_imageiread_imageui时,采样器的filter_mode必须设置为CLK_FILTER_NEAREST
  • 使用read_imagef时,如果坐标是整数,那么filte_mode必须设置为CLK_FILTER_NEAREST
  • 使用read_imageX时,X表示**,如果坐标是整数,那么采样器的坐标正则化必须设置为CLK_NORMALIZED_COORDS_FALSE,且address mode必须设置为CLK_ADDRESS_CLAMP_TO_EDGE, CLK_ADDRESS_CLAMP 或者 CLK_ADDRESS_NONE
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
OpenCL是一种基于开放标准的并行计算框架,它可以在CPU、GPU、FPGA等不同类型的处理器上运行并发程序,因此非常适合于图像处理应用。下面是一个可能的OpenCL图像处理项目实战: 1. 确定需求:首先需要明确你的图像处理需求,比如说你想实现什么样的滤镜、特效、色彩调整等等。这个需求决定了你需要实现的OpenCL内核函数。 2. 获取图像数据:从文件或者摄像头等输入设备中获取图像数据,这些数据可以是RGB格式、灰度图像格式等。 3. 创建并初始化OpenCL环境:使用OpenCL API创建并初始化OpenCL环境,包括创建OpenCL上下文、命令队列、内存对象等等。 4. 实现OpenCL内核函数:根据需求编写OpenCL内核函数,这些函数将在OpenCL设备上并行计算,通常包括对图像数据的遍历、像素值的计算等操作。 5. 将图像数据传输到OpenCL设备:将获取到的图像数据复制到OpenCL设备的内存中,以便内核函数能够访问。 6. 调用OpenCL内核函数:使用OpenCL API调用内核函数,将其提交到OpenCL设备上执行。 7. 获取计算结果:使用OpenCL API从设备内存中读取计算结果,通常是一个经过处理的图像数据。 8. 显示图像:将计算结果显示出来,可以是在窗口中显示、保存到文件中等方式。 这些步骤只是OpenCL图像处理项目实战的大致流程,具体实现还需要根据实际需求进行调整。同时,OpenCL图像处理也是一个非常庞大、复杂的领域,需要掌握一定的图像处理算法和OpenCL编程技术才能实现高质量的应用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值