SepFilter2d

The operator applies separable linear filters to the image, decomposing the filtering of a two-dimensional image into a horizontal one-dimensional filter and a vertical one-dimensional filter. Each row is convolved with a one-dimensional filter kernelX, and then each column of the result is convolved with a one-dimensional filter kernelY. Decomposable filter kernels include, but are not limited to, Sobel derivative kernel, Gaussian filter kernel, box filter kernel, median filter kernel, and so on.

Operator Effect

Input ImageParameterOutput Image
imagekernel=[0.0833333,0.0833333,0.66666,0.0833333,0.0833333]image

Principle

The computational efficiency can be improved by splitting a 2D filter kernel into two separable 1D filter kernels. The specific principle is that a decomposable filtering kernel can be understood as two one-dimensional kernels. The x-filtering kernel is called first and then the y-filtering kernel is called during convolution. The consumption incurred by the convolution of two matrices can be estimated as the product of the areas of the two matrices, such that the time required to convolve an image of area A with an n×n convolution kernel is A*n^2, but if it is decomposed into two kernels of n×1 and 1×n, then the cost is A*n + A*n = 2A*n,. Thus decomposing the convolution kernel improves the efficiency of convolution computation.

Note

This calculation is efficient as long as n is not less than 3, and the benefit becomes more apparent as n increases.

API Interface

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

For detailed interface information, please refer to hbVPSepFilter2D.

Usage

// 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);