SepFilter2d

算子对图像应用可分离的线性滤波器,把对二维图像的滤波分解为横向一维滤波和纵向一维滤波。每一行与一维的滤波核kernelX做卷积, 然后运算结果的每一列与一维的滤波核kernelY做卷积。可分解的滤波核包括但不限于Sobel导数核、高斯滤波核、盒式滤波核、中值滤波核等。

算子效果

输入图像参数输出图像
imagekernel = [0.0833333,0.0833333,0.66666,0.0833333,0.0833333]
borderType = HB_VP_BORDER_REPLICATE
image

原理

将一个二维滤波核拆解为两个可分离的一维滤波核,可以提高计算效率。具体原理为一个可以分解的滤波核可以理解成两个一维核, 在卷积时先调用x滤波核,然后调用y滤波核。两个矩阵进行卷积所产生的消耗可以用两个矩阵的面积的积来估算,如此一来, 用n×n的卷积核对面积为A的图像进行卷积所需的时间是A*n^2,但如果分解成 n×1 和 1×n 的两个核,那么代价就是 A*n + A*n = 2A*n,因此分解卷积核可以提高卷积计算的效率。

注解

只要n不小于3,这种计算方式就能提高效率,并且随着n的增大,这种效益愈发明显。

API接口

int32_t hbVPSepFilter2D(hbUCPTaskHandle_t *taskHandle,
                        hbVPImage *dstImg,
                        hbVPImage const *srcImg,
                        hbVPFilterKernel const *filterKernelX,
                        hbVPFilterKernel const *filterKernelY,
                        hbVPSepFilter2DParam const *sepFilter2DParam);

详细接口信息请查看 hbVPSepFilter2D

使用方法

// Include the header
#include "hobot/hb_ucp.h"
#include "hobot/vp/hb_vp.h"
#include "hobot/vp/hb_vp_sep_filter2d.h"

// init Image, allocate memory for image data
hbUCPSysMem src_mem;
hbUCPMallocCached(&src_mem, src_stride * src_height, 0);
hbVPImage src_img{HB_VP_IMAGE_FORMAT_Y,
                  HB_VP_IMAGE_TYPE_U8C1,
                  src_width,
                  src_height,
                  src_stride,
                  src_mem.virAddr,
                  src_mem.phyAddr,
                  nullptr,
                  0,
                  0};

hbUCPSysMem dst_mem;
hbUCPMallocCached(&dst_mem, dst_stride * dst_height, 0);
hbVPImage dst_img{HB_VP_IMAGE_FORMAT_Y,
                  HB_VP_IMAGE_TYPE_U8C1,
                  dst_width,
                  dst_height,
                  dst_stride,
                  dst_mem.virAddr,
                  dst_mem.phyAddr,
                  nullptr,
                  0,
                  0};

// init kernel 
hbVPFilterKernel kernel_x;
kernel_x.dataType = HB_VP_IMAGE_TYPE_F32C1;
kernel_x.width = 5;
kernel_x.height = 1;
hbUCPSysMem kernel_x_mem;
hbUCPMallocCached(&kernel_x_mem, kernel_x.width * kernel_x.height * sizeof(float32_t), 0);
kernel_x.dataPhyAddr = kernel_x_mem.phyAddr;
kernel_x.dataVirAddr = kernel_x_mem.virAddr;

hbVPFilterKernel kernel_y;
kernel_y.dataType = HB_VP_IMAGE_TYPE_F32C1;
kernel_y.width = 1;
kernel_y.height = 5;
hbUCPSysMem kernel_y_mem;
hbUCPMallocCached(&kernel_y_mem, kernel_y.height * kernel_y.width * sizeof(float32_t), 0);
kernel_y.dataPhyAddr = kernel_y_mem.phyAddr;
kernel_y.dataVirAddr = kernel_y_mem.virAddr;

// init param
hbVPSepFilter2DParam vp_param;
vp_param.borderType = HB_VP_BORDER_REPLICATE;

// init task handle and schedule param
hbUCPTaskHandle_t task_handle{nullptr};
hbUCPSchedParam sched_param;
HB_UCP_INITIALIZE_SCHED_PARAM(&sched_param);
sched_param.backend = HB_UCP_DSP_CORE_0;

// create task
hbVPSepFilter2D(&task_handle, &dst_img, &src_img, &kernel_x, &kernel_y, &vp_param);

// submit task
hbUCPSubmitTask(task_handle, &sched_param);

// wait for task done 
hbUCPWaitTaskDone(task_handle, 0);

// release task handle
hbUCPReleaseTask(task_handle);

// release memory
hbUCPFree(&src_mem);
hbUCPFree(&dst_mem);
hbUCPFree(&kernel_x_mem);
hbUCPFree(&kernel_y_mem);