使用图像对象的理由

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

  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

OpenCL:图像处理基础note的更多相关文章

  1. MATLAB图像处理基础

    MATLAB图像处理基础 2.2.1 图像文件格式及图像类型 1.MATLAB支持的几种图像文件格式: ⑴JPEG(Joint Photogyaphic Expeyts Group):一种称为联合图像 ...

  2. GPU 服务器环境安装中一些基础note

    GPU 服务器环境安装中一些基础note GPU 服务器: 添加组,用户,并为之新建主目录. c302@c302-dl:~$ sudo addgroup testgroup Adding group ...

  3. Matlab图像处理基础知识

    Matlab图像处理基础知识 Matlab的图片以矩阵的形式存储,矩阵的行列值为图片的行列的色彩值. 1图像表达方式: 像素索引 图像被视为离散单元.如使用I(2,2)可以获取第二行第二列的像素值 空 ...

  4. Java知多少(100)图像处理基础

    图像是由一组像素构成,用二进制形式保存的图片.java语言支持GIF.JPEG和BMP这3种主要图像文件格式.java语言的图像处理功能被封装在Image类中. 图像载入和输出 在java程序中,图像 ...

  5. Java数字图像处理基础 - 必读

    写了很多篇关于图像处理的文章,没有一篇介绍Java 2D的图像处理API,文章讨论和提及的 API都是基于JDK6的,首先来看Java中如何组织一个图像对象BufferedImage的,如图: 一个B ...

  6. 图像处理基础---RGB图 灰度图 索引图 调色板

    (1)二进制图 在二进制图中,像素的取值为两个离散数值0或1中的一个,0代表黑色,1代表白色 例 A=[0 0 1;1 1 0; 0 0 1];>> imshow(A,'InitialMa ...

  7. opencv图像处理基础 (《OpenCV编程入门--毛星云》学习笔记一---五章)

    #include <QCoreApplication> #include <opencv2/core/core.hpp> #include <opencv2/highgu ...

  8. Python3 OpenCV3 图像处理基础

    开发环境搭建 本人使用的是Ubuntu 16.04LTS. 1.安装Python3 ## 其实 Ubuntu 16.04 系统自带了 Python 3.5.2,因此不需要再安装了?但是需要安装一些开发 ...

  9. opencv-python图像处理基础(一)

    #一.读取图像数据 import cv2 img=cv2.imread("d:/image0.JPG") #读取图片数据 print(img) cv2.imshow('image' ...

随机推荐

  1. CSS3禁止用户选中文字——user-select: none;

    需求:现在有一个需求是在移动端让你禁止用户选中文字,你会怎么做呢?如下图    解决方法:使用CSS3新增属性 user-select: none;   -webkit-user-select:non ...

  2. [Swift]LeetCode93. 复原IP地址 | Restore IP Addresses

    Given a string containing only digits, restore it by returning all possible valid IP address combina ...

  3. [Swift]LeetCode817. 链表组件 | Linked List Components

    We are given head, the head node of a linked list containing unique integer values. We are also give ...

  4. [Swift]LeetCode934. 最短的桥 | Shortest Bridge

    In a given 2D binary array A, there are two islands.  (An island is a 4-directionally connected grou ...

  5. 【dotNet Core】Swagger下简单的给WebApi分组

    Startup.cs下ConfigureServices代码 这里主要在DocInclusionPredicate控制输出那些api. Startup.cs下Configure代码 给Controll ...

  6. Python中面向对象的概念(科普)

    面向对象(OOP)基本概念 面向对象编程 —— Object Oriented Programming 简写 OOP 目标 了解 面向对象 基本概念 01. 面向对象基本概念 我们之前学习的编程方式就 ...

  7. javascript 常见数组操作( 1、数组整体元素修改 2、 数组筛选 3、jquery 元素转数组 4、获取两个数组中相同部分或者不同部分 5、数组去重并倒序排序 6、数组排序 7、数组截取slice 8、数组插入、删除splice(需明确位置) 9、数组遍历 10、jQuery根据元素值删除数组元素的方)

    主要内容: 1.数组整体元素修改 2. 数组筛选 3.jquery 元素转数组 4.获取两个数组中相同部分或者不同部分 5.数组去重并倒序排序 6.数组排序 7.数组截取slice 8.数组插入.删除 ...

  8. solr之环境配置一

    安装Java JDK solr运行需要java serverlet 容器,默认使用jetty,或者tomcat,jboss等等. 下载一个jdk,我的jdk是jdk1.7.0_65. 安装JDK的步骤 ...

  9. 大战Java虚拟机【3】—— 类加载机制

    前言 当你的代码编译成class文件之后,那么虚拟机如何加载这些文件呢?我们需要知道虚拟机到底做了什么样的事情. 类的生命周期 加载--链接---初始化----使用---卸载 类加载过程 1.加载 读 ...

  10. C#2.0导航

    主要特性 泛型 类型和方法的参数化 可空类型 值类型可为null 委托 更简化的方式 迭代器 简单的foreach,不简单的状态机