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]
borderType = HB_VP_BORDER_REPLICATE
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 
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, 5 * 1 * 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);