Canny是图像处理中经常用到的一种边缘检测算法,Canny的具体算法流程:
(1)根据sobel后的结果,通过幅值和角度进行非极大值抑制
(2)对非极大值抑制后的结果进行双阈值处理
(3)双阈值后的图像,进行边缘连接,得到连续性较好的边缘信息
更加具体的理论可以参考:点击打开链接,本文主要是参考opencv源码实现的Canny,具体代码如下:
void canny(image_uchar_ptr image, image_grad_ptr gradImg, image_uchar_ptr cannyImg, UCHAR **stack,int low, int high, int w, int h) { sobel_grad_direction(image, gradImg,w,h); UINT *gmag_ptr = gradImg->gmag + w; INT *gx_ptr = gradImg->g_x + w; INT *gy_ptr = gradImg->g_y + w; UCHAR *canny_ptr = cannyImg->data + w; UCHAR **stack_top = &stack[0]; UCHAR **stack_bottom = &stack[0]; #define _PUSHKK(d) *(d) = (UCHAR)(2), *stack_top++ = (d) #define _POPKK(d) (d) = *--stack_top int y = 0, x = 0,yy = 0,xx = 0; for (int i = 1; i < h - 1; i++) { gmag_ptr[0] = 0; gmag_ptr[w - 1] = 0; canny_ptr[0] = 1; canny_ptr[w - 1] = 1; int prev_flag = 0; for (int j = 1; j < w - 1; j++) { int m = gmag_ptr[j]; if (m > low) { int xs = gx_ptr[j]; int ys = -gy_ptr[j]; int x0 = abs(xs); int y0 = abs(ys) << CANNY_SHIFT; int tg22x = x0 * TG22; if (y0 < tg22x) { if (m > gmag_ptr[j - 1] && m >= gmag_ptr[j + 1]) { goto __ocv_canny_push; } } else { int tg67x = tg22x + (x0 << (CANNY_SHIFT + 1)); if (y0 > tg67x) { if (m > (gmag_ptr - w)[j] && m >= (gmag_ptr + w)[j]) { goto __ocv_canny_push; } } else { int s = (xs ^ ys) < 0 ? -1 : 1; if (m > (gmag_ptr - w)[j - s] && m > (gmag_ptr + w)[j + s]) { goto __ocv_canny_push; } } } } prev_flag = 0; canny_ptr[j] = (UCHAR)(1); continue; __ocv_canny_push: if (!prev_flag && m > high && (canny_ptr - w)[j] != 2) { _PUSHKK(canny_ptr + j); prev_flag = 1; } else canny_ptr[j] = 0; } gmag_ptr += w; gx_ptr += w; gy_ptr += w; canny_ptr += w; } while (stack_top > stack_bottom) { uchar *m; _POPKK(m); if (!m[-1]) _PUSHKK(m - 1); if (!m[1]) _PUSHKK(m + 1); if (!m[-w - 1]) _PUSHKK(m - w - 1); if (!m[-w]) _PUSHKK(m - w); if (!m[-w + 1]) _PUSHKK(m - w + 1); if (!m[w - 1]) _PUSHKK(m + w - 1); if (!m[w]) _PUSHKK(m + w); if (!m[w + 1]) _PUSHKK(m + w + 1); } canny_ptr = cannyImg->data + w; for (int i = 1; i < h - 1; i++) { for (int j = 1; j < w - 1; j++) { canny_ptr[j] = 256 -(canny_ptr[j] >> 1); } canny_ptr += w; } }若发现有不当之处,欢迎指正讨论,谢谢!