OpenCL 通用编程与优化(16)
9.3图像相关操作
Adrenogpu有内置的硬件模块,可以加速常见的滤波操作,包括卷积、方框滤波、SAD(绝对差之和)和SSD(平方差之和)等。与使用通用的OpenCL内核语言相比,使用这些模块可以获得更好的性能或消耗更少的功率。
9.3.1卷积操作
卷积滤波器运算将图像样本值矩阵相乘为滤波器权值矩阵,并将结果求和得到输出值。要使用扩展,应用程序需要创建一个特殊的图像对象,并详细描述其中的权重矩阵,如下示例所示:
weight_img_desc.image_desc.image_type =CL_MEM_OBJECT_WEIGHT_IMAGE_QCOM;
weight_img_desc.image_desc.image_width = filter_size_x;
weight_img_desc.image_desc.image_height = filter_size_y;
weight_img_desc.image_desc.image_array_size = num_phases;
weight_img_desc.image_desc.image_row_pitch = 0; // must set to zero
weight_img_desc.image_desc.image_slice_pitch = 0; // must set to zero
weight_img_desc.weight_desc.center_coord_x = center_coord_x;
weight_img_desc.weight_desc.center_coord_y = center_coord_y;
// specify separable filter. Default (flags=0) is 2D convolution filter
weight_img_desc.weight_desc.flags = CL_WEIGHT_IMAGE_SEPARABLE_QCOM;
权重矩阵描述符包含该操作所需的所有信息。除了宽度、高度等正则图像性质外,还需要权重矩阵的中心坐标和卷积类型,即是否可分离。在此扩展中,支持两种类型的卷积滤波器,二维卷积滤波器和可分离卷积滤波器。
- 对于二维卷积滤波器:
- 该滤波器是由一组(filter_size_x * filter_size_y)权重元素指定的二维矩阵
- 滤波器的中心点,其坐标是基于滤波器空间区域左上角的原点。
- 图9-1展示了一个大小为10x10的二维卷积滤波器,其中心点位于坐标处(cx = 1,cy = 1)。
- 位于图像矩阵中(3、2)处的像素是位于权重矩阵中(1、1)处的像素的倍数。
- 图像中的其他像素乘以权重矩阵中对应的像素。
- 位于(3、2)处的输出值将是前面步骤的总和。
图9-1二维卷积滤波器示例
- 可分离卷积滤波器:
- 该滤波器是一个二维滤波器,可以由x和y方向上的两个一维滤波器指定,这样它们的产品就会产生二维滤波器。
- 可分离滤波器可以通过使用一维水平滤波器对每一行进行一维卷积,然后使用一维垂直滤波器对结果的每列进行卷积。
- 该结果在数学上与直接对每个像素应用二维滤波器相同。
- 对于具有多个阶段的用例,可分离的滤波器可以提供一个性能优势,因为计算的数量减少了一个数量级。
- 图9-2显示了一个二维滤波器及其相关的可分离过滤器的例子。
图9-2可分离的二维滤波器的示例
表9-3列出了权重矩阵的关键参数及其描述和限制。
表9-3重量矩阵的要求
参数 | 描述和要求 |
---|---|
图像类型标志 | CL_MEM_READ_ONLY和CL_MEM_COPY_HOST_PTR。权重图像只支持从内核进行的读取访问。 |
image_format | 使用clGetSupportedImageFormats进行查询,图像类型设置为CL_MEM_OBJECT_WEIGHT_IMAGE_QCOM。 |
二维卷积滤波器: num_phases | num_phases = num_phase_x * num_phase_y .它要求两个值(num_phase_x = num_phase_y)都必须是2的幂次值。每个滤波器阶段的权重值被组织成一个二维切片大小(filter_size_x * filter_size_y)。 |
可分离的num_phases | num_phases=num_phase_x=num_phase_y(必须为2的电源)。每个滤波器相位的一维水平和一维垂直滤波器的权重被组织成一个二维切片,切片高度=2和切片宽度= max(filter_size_x,filter_size_y)。 |
如果num_phases大于1,则为权重切片 | 权重切片必须组织在一个二维数组中,该数组的片数等于num_phases。在内置执行期间,相位值是根据滤波器中心点的坐标与像素中心的亚像素偏移量的分数来计算的。 |
卷积函数的限制:
- 对于执行函数qcom_convolve_imagef的工作组内的所有工作项,输入的<图像>、<权重_图像>和<采样器>必须是统一的。
- 过滤器阶段的数量不能超过平台的最大阶段的数量,这可以使用clGet设备信息查询,<param_name>设置为CL_DEVICE_HOF_MAX_NUM_PHASES_QCOM。
- filter_size_x/y不能超过平台的最大过滤器大小,可以使用clGet数据信息查询,<param_name>设置为CL_DEVICE_HOF_MAX_FILTER_SIZE_X_QCOM和CL_DEVICE_HOF_MAX_FILTER_SIZE_Y_QCOM。
- 内置的卷积滤波器不适用于多平面平面图像。
9.3.2盒式过滤器
盒滤波器是一种线性操作,取盒滤波器覆盖的源图像空间区域内像素的平均值。框过滤器由(box_filter_width,
box_filter_height)和框过滤器中心所在的坐标指定。数学上,以坐标(x,y)为中心的盒子滤波器产生的像素的线性平均值计算如下:
box_filter(x, y) = sum(weight(i, j) * pix(i, j)) / (box_width *
box_height)
其中(i,j)是box过滤器所覆盖的像素的坐标。需要注意的是,一些像素可能只被盒子部分覆盖。因此,权重(i、j)是根据方框中像素(i、j)的覆盖范围进行调整的。例如,如果像素被覆盖了50%,则权重将为0.5。图9-3显示了一个应用于5x6图像的2x2盒滤波器的示例。重量是由内置的硬件自动计算出来的。
Figure 9-3 Box filtering example when pixels are partially covered
由于方框过滤器以坐标(2,2)为中心,因此该过滤器覆盖了9个像素。根据滤波器所覆盖的像素,对权重进行如下调整:
W(0, 0) = 0.25 W(1, 0) = 0.5 W(2, 0) = 0.25
W(0, 1) = 0.5 W(1, 1) = 1 W(2, 1) = 0.5
W(0, 2) = 0.25 W(1, 2) = 0.5 W(2, 1) = 0.25
图9-4显示了一个3x3滤波器,其中源图像的所有像素被完全覆盖。因此,对于这个滤波,每个像素的权重是相等的。
图9-4当像素被完全覆盖时的方框过滤示例
内置的盒子过滤器功能定义如下:
float4 qcom_box_filter_imagef(image2d_t image, sampler_t sampler, float2
coord, const qcom_box_size_t box_size);
- 参数指定一个有效的可读图像,其中应用了框过滤器。
- 参数指定了读取<图像>的采样模式。
- 参数指定方框滤波器的中心位于源图像平面上的点的坐标。只能使用浮点坐标,否则内核将无法编译。
- 参数<box_size>指定框box_filter_width和box_filter_height。box_size必须作为OpenCL内核参数传入,并且必须在内核运行时进行修复。
功能限制: - 对于执行qcom_box_filter_imagef函数的工作组中的所有工作项,输入的、<box_size>和必须是统一的。
- box_size.x/.y不能超过平台的最大盒过滤器大小,可以使用clGetDeviceInfo,<param_name>设置为CL_DEVICE_HOF_MAX_FILTER_SIZE_X_QCOM和CL_DEVICE_HOF_MAX_FILTER_SIZE_Y_QCOM。
- <box_size>必须作为OpenCL内核参数传入,并且必须在内核运行时进行修复。
- 内置的盒式滤波器不适用于多平面平面图像
有关更多细节和代码示例,请参阅Adreno OpenCL SDK文档。