SepFilter2d

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

算子效果

输入图像参数输出图像
imagekernel=[0.0833333,0.0833333,0.66666,0.0833333,0.0833333]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 hbUCPSysMem kernel_x_mem; hbUCPMallocCached(&kernel_x_mem, 5 * 1 * sizeof(float32_t), 0); hbVPFilterKernel kernel_x; kernel_x.dataType = HB_VP_IMAGE_TYPE_F32C1; kernel_x.width = 5; kernel_x.height = 1; kernel_x.dataPhyAddr = kernel_x_mem.phyAddr; kernel_x.dataVirAddr = kernel_x_mem.virAddr; hbUCPSysMem kernel_y_mem; hbUCPMallocCached(&kernel_y_mem, 5 * 1 * sizeof(float32_t), 0); hbVPFilterKernel kernel_y; kernel_y.dataType = HB_VP_IMAGE_TYPE_F32C1; kernel_y.width = 1; kernel_y.height = 5; 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);