Canny之c语言实现

时间:2021-10-03 16:33:27

    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;
	}

}
若发现有不当之处,欢迎指正讨论,谢谢!