Canny

Canny算子是一种边缘检测器,它使用多阶段算法来检测图像中的大范围边缘。

算子效果

输入图像参数输出图像
imagethreshold1 = 100
threshold2 = 400
kernelSize = 3
norm = HB_VP_NORM_L1
overlap = 64
borderType = HB_VP_BORDER_REPLICATE
image

原理

算子的计算过程分为多个阶段:

  1. 梯度计算

输入图像在垂直和水平方向上使用Sobel内核进行卷积,核大小由Sobel尺寸参数确定。然后在水平和垂直方向上使用边缘检测过滤器进行过滤,从而产生 Gx 和 Gy。 每个像素的强度和角度计算如下:

Intensity=dx2+dy2Intensity=\sqrt{dx^2+dy^2}

Angle=arctan(dydx)Angle=arctan(\frac{dy}{dx})

  1. 非极大值抑制 (non-maximum suppression)

对于图像中的每个像素,检查强度是否是梯度方向上的局部最大值。如果是,则将其保留为边缘像素,否则将其作为非边缘像素移除。

  1. 双重阈值化

将每个像素的强度大小与强阈值(ℎ𝑖𝑔ℎ_𝑡ℎ𝑟𝑒𝑠ℎ𝑜𝑙𝑑)和弱阈值(𝑙𝑜𝑤_𝑡ℎ𝑟𝑒𝑠ℎ𝑜𝑙𝑑)进行比较,如果强度大于强阈值,则将其标记为强边缘。如果强度小于弱阈值,则标记为无边缘。强阈值和弱阈值之间的强度值都被标记为弱边缘。

  1. 边缘追踪

如果弱边连接到强边,那么这条弱边就变成了强边。重复这个过程,直到找到所有连接到强边的弱边。然后将其余的弱边标记为非边,就得到了整个图像的边缘检测结果。

API接口

int32_t hbVPCanny(hbUCPTaskHandle_t *taskHandle, hbVPImage *dstImg, hbVPImage const *srcImg, hbVPCannyParam const *cannyParam);

详细接口信息请查看 hbVPCanny

使用方法

// Include the header #include "hobot/hb_ucp.h" #include "hobot/vp/hb_vp.h" #include "hobot/vp/hb_vp_canny.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 param hbVPCannyParam canny_param; canny_param.threshold1 = 100; canny_param.threshold2 = 400; canny_param.kernelSize = 3; canny_param.norm = 1; canny_param.overlap = 64; canny_param.borderType = 1; // 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 hbVPCanny(&task_handle, &dst_img, &src_img, &canny_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);