1.OpenCL提供了大量可以在内核中运行的图像处理函数,它们大致可以分为以下三类:
(1)Read functiongs--返回给定坐标上的颜色取值;
(2)write functiongs-- 设定给定坐标上的颜色取值;
(3)Information functions-- 提供关于图像对象的信息,例如图像的维度以及像素属性;
图像读取函数是从图像对象中读取向量,他们各自的参数基本一样。唯一的区别是函数返回的是浮点数向量还是整数向量,读取的是二维图像对象还是三维图像对象。
读取图像数据的内核函数:
1.float4 read_imagef(image2d_t img,sampler_t sampler, int2/float2 coord)--以float4型向量的形式读取二维图像在coord位置的颜色数据;
2.int4 read_imagei(image2d_t img,sampler_t sampler, int2/float2 coord)--以int4型向量的形式读取二维图像在coord位置的颜色数据;
3.uint4 read_imagui(image2d_t img,sampler_t sampler, int2/float2 coord)--以uint4型向量的形式读取二维图像在coord位置的颜色数据;
4.float4 read_imagef(image3d_t img,sampler_t sampler, int4/float4 coord)--以float4型向量的形式读取三维图像在coord位置的颜色数据;
5.int4 read_imagei(image3d_t img,sampler_t sampler, int4/float4 coord)--以int4型向量的形式读取三维图像在coord位置的颜色数据;
6.uint4 read_imagui(image3d_t img,sampler_t sampler, int4/float4 coord)--以uint4型向量的形式读取三维图像在coord位置的颜色数据;
如果图像对象是一个image2d_t类型,坐标的格式就必须是int2型或float2型。
如果图像对象是一个image3d_t类型,坐标的格式就必须是int4型或float4型。
你想从名为image的二维图像对象中读取坐标为(3,4)的颜色数据。如果希望颜色取值是float4型向量,函数调用为:
float4 color = read_imagef(image, sampler, (int2)(3,4));
read_imagef函数的返回值范围由image格式来确定。如果像素是无符号归一化格式(CL_UNORM_INT8,CL_UNORM_INT16,CL_UNORM_INT101010,CLUNORM_SHORT565,或CL_UNORM_SHORT555),函数的返回值就必须在0.0和1.0之间。如果像素是有符号归一化格式(CL_SNORM_INT8或CL_SNORM_INT16),read_imagef函数的返回值就必须在-0.5和0.5之间。如果像素的格式是CL_HALF_FLOAT或CL_FLOAT,函数的返回值将是正常的浮点数。
read_image函数返回的颜色向量:(通道顺序 向量存储(整数))
CL_R,CL_Rx --(R, 0, 0, 1)
CL_A--(0, 0, 0, A)
CL_RG,CL_RGx--(R, G, 0 ,1)
CL_RA--(R, 0, 0, A)
CL_RGB, CL_RGBx--(R, G, B, 1)
CL_RGBA,CL_BGRA, CL_ARGB--(R,G,B,A)
CL_INTENSITY--(I, I, I, I)
CL_LUMINANCE--(L, L, L, 1)
表中的数字全部都是整数,但如果向量是read_imagef函数的返回值,它的分量就是浮点数。如果,图像对象的像素都是CL_RG格式,read_imagef函数所返回的向量将是[R, G, 0.0, 1.0],其中R和G分别表示的是像素的红色和绿色分量。
将数据写入图像对象的内核函数:
1.void write_imagef(image2d_t img, int2 coord, float4 color)--将float4型颜色数据写到二维图像中coord所指定的位置。
2.void write_imagei(image2d_t img, int2 coord, int4 color)--将int4型颜色数据写到二维图像中coord所指定的位置。
3.void write_imageui(image2d_t img, int2 coord, uint4 color)--将uint4型颜色数据写到二维图像中coord所指定的位置。
4.void write_imagef(image3d_t img, int4 coord, float4 color)--将float4型颜色数据写到三维图像中coord所指定的位置。
5.void write_imagei(image3d_t img, int4 coord, int4 color)--将int4型颜色数据写到三维图像中coord所指定的位置。
6.void write_imageui(image3d_t img, int4 coord,uint4 color)--将uint4型颜色数据写到三维图像中coord所指定的位置。
默认情况下,并不支持将数据写入到三维图像对象中。这个功能需要通过cl_khr_3d_image_writes扩展来实现,因此,如果想要修改image3d_t对象中的数据,需要在内核中加入下面一行代码,确认是否能有这个扩展:
#pragma OPENCL EXTENSION cl_khr_3d_image_writes: enable
为了设定代写的颜色数据。例如,如果像素的RGB分量 是[132,15,44], 你可以将像素数据写到CL_RGB型图像对象img中:
write_imageui(img, coord, (uint4)(132,15,44,0));
图像信息函数
获取推向信息的内核函数:
(1)int get_image_width(image2d_t/image3d_t image)--返回图像的宽度;
(2)int get_image_height(image2d_t/image3d_t image)--返回图像的高度;
(3)int get_image_depth(image3d_t image)--返回图像的深度;
(4)int2 get_image_dim(image2d_t image)--以int2型向量的形式,返回二维图像的宽度和高度;
(5)int4 get_image_dim(image3d_t image)--以int4型向量的形式,返回三维图像的宽度、高度和深度;
(6)int get_image_channel_data_type(mage2d_t/image3d_t image)--返回图像的通道数据类型(CLK_UNORM_INT8,CLK_SIGNED_INT32.等)
(7)int get_image_channel_order(image2d_t/image3d_t image)--返回图像的通道(CLK_A,CLK_RGB,CLK_INTENSITY等)
注意内核并不接受采样器作为它的参数。所以,程序在内核函数之前,创建了以一个sampler_t型的sampler对象。
图像放缩和插值:
图像的放大是很重要的问题,因为涉及到的是增加像素信息,而不是溢出已有的像素。如果NN的像素放大k倍,得到的图像是kNkN大小的图像。现在重要的问题是:如何获取放大后的图像中那(k的平方减一)N的平方个像素的颜色取值。
一种方法是重复原始图像中的某些像素。称为最近邻插值法。但是如果需要绘制穿过像素中心点的直线,并用这些直线来近似已知像素点之间的各点,这种方法也被称为双线插值法,这种方法所需的工作量大,但相应的,产生的结果也更好。如果配置正确,采样器可以告诉内核自动选择最近邻插值法(CL_FILTER_NEAREST),还是双线性插值法(CLK_FILTER_LINEAR).
注意:像素插值法只有在图像的坐标是浮点数的前提下才能完成,如果图像的坐标是整数,得到的插值法结果将完全和其中某个像素的颜色一样。
最近邻插值(CL_FILTER_NEAREST):
如果相对于其他的像素点,待处理的点更靠近像素A,那么,那个点上的采样颜色就会被设为像素A的颜色。这种方法可以用来放大图像,处理得到的图像只包含原来图像的颜色。如果图像被放大k倍,图像上的每个点都会重复k次。
最近邻插值法的运行速度很快,因为它并不需要任何的数学计算。但如果用它来放大图像,得到的结果会看起来粒状化和像素点化(grainy和pixelated).放大后的图像有一个问题,就是像素点取址之间的突变。即使是灰度图像,也能明显地看到汽车像素点之间颜色的非连续变化。
双线性插值法CLK_FILTER_LINEAR):
如果一个点是在矩形图像的两个已有像素之间时,它采样的颜色将被设为两个像素颜色的线性组合:
(1)使用CLK_FILTER_LINEAR的前提是坐标必须是浮点数;
(2)只有read_imagef函数有这个选项。如果将采样器设为CLK_FILTER_LINEAR,调用read_imageuior read_imagei函数,结果将是未定义的。
(3)有些OpenCL兼容设备并不支持双线性插值。如果是那样的话,就需要通过硬件模拟的方式来插值。
小结:
OpenCL标准定义了大量和图像相关的数据类型和函数。如果一个内核处理图像,它会将图像数据作为图像对象(image2d_t型对象或image3d_t型对象)来读入。为了从图像对象中读取数据,内核需要一个sampler_t型对象。这个对象可以用来控制内核读取坐标,插值运算的方式。
OpenCL的图像处理函数可以分为三类:从图像对象中读取数据的函数,将数据写入到图像对象的函数,以及访问和图像有关的信息(例如图像的大小,以及像素属性)的函数。读函数需要采样器对象,而坐标可以按整数或浮点数的形式给出。然而,写函数却要求的是整数坐标。此外,三维图像不能直接写入到图像对象中,除非设备支持cl_khr_3d_image_writer扩展。
可以对采样器进行配置,设置相邻像素之间颜色数据的插值方式,这也让采样器在图像处理中扮演了一个颇为重要的角色。OpenCL提供了两种插值方法:最近邻插值法CLK_FILTER_NEAREST以及双线性插值法CLK_FILTER_LINEAR.当用最邻近插值法来放缩图像时,它会在原始图像中重复像素信息。这种方法的又是是运行速度快,但如果采用双线性插值法,能取得更好的插值效果。双线性插值法通过使用直线连接两个像素的中心,然后来计算相邻像素之间的颜色取值。但是,这种插值方法只适用于坐标和颜色取值都是浮点数的情况。