OpenCL:圖像處理基礎note(轉)

使用圖像對象的理由

雖然對於圖像也可以把它的像素數據當做一般的緩存數據來處理,但是如果把它當做圖像來處理有如下好處:

  1. 在GPU中,圖像數據是保存在特殊的全局內存中,即紋理內存,它和一般的全局內存不相同,它是被緩存的,用於高速訪問處理。GPU中有專門支持圖像讀寫的硬件,使用內置讀寫函數可以充分發揮這個優勢
  2. 只要OpenCL支持該圖像格式,那麼就可以不用考慮圖像格式的前提下使用讀寫圖像數據的函數
  3. 可以使用採樣器來配置讀取圖像中數據的的方式
  4. OpenCL提供函數來獲取圖像相關信息,比如寬度等

主機與內核的命名

圖像相關應用主要涉及兩個數據類型,即圖像對象採樣器。圖像對線用來保存主機和設備上的圖像對象,而採樣器則在設備接收數據時,說明如何讀取這些顏色值

  圖像對象 採樣器
主機 cl_mem (和一般緩存對象一樣) cl_sampler
設備 image2d_t或者image3d_t sampler_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
發佈了15 篇原創文章 · 獲贊 36 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章