20世纪70年代末,David Marr 尝试将生物视觉融合进一个可以用于机器视觉的模型。Marr描述道“早期视觉处理的目标是对图像构建一个原始但丰富的描述,用于确定可视表面的反射系统和光强度,以及它们相对于观察者的方向的距离”[1]。他把最低级别的描述称为原始要素图,其中最主要的组成部分是边缘。
根据[1]中,我们可以将一个边缘检测算法描述为:
我们可以通过差分进行计算,面这个例子中顺序并没有关系,因些可以通过分析法计算高斯拉普拉斯算子(Laplacian of the Gaussina,LoG),并且采样这个函数。创建一个卷积掩模;可以对图像应用这个卷积掩模产生同样的结果。在此,给出相应的代码:
float LoG (float x, float sigma){ float x1; x1 = gauss (x, sigma); return (x*x-2*sigma*sigma)/(sigma*sigma*sigma*sigma) * x1; }在此需要识别出零交叉,标记出在这些位置处的像素(设P),P处零交叉意味着某个方向两个相对的相邻像素的值的符号不同。我们通过zero_cross函数LoG中的每一像素进行执行。
void zero_cross (float **lapim, IMAGE im)
为了确保使用了多种不同的尺度,使用了两个不同的高斯函数,并且将两种尺度下具有零交叉的像素选择出来作为输出边缘像素。当然,还可以使用两个以上的高斯函数。在此贴出Marri算法代码。
void marr (float s, IMAGE im){ int width; float **smx; int i,j,k,n; float **lgau, z; //Create a Gaussian and a derivative of Gaussian filter mask width = 3.35*s + 0.33; n = width+width + 1; printf ("Smoothing with a Gaussian of size %dx%d\n", n, n); lgau = f2d (n, n); for (i=0; i<n; i++) for (j=0; j<n; j++) lgau[i][j] = LoG (distance ((float)i, (float)j,(float)width, (float)width), s); //Convolution of source image with a Gaussian in X and Y directions smx = f2d (im->info->nr, im->info->nc); printf ("Convolution with LoG:\n"); convolution (im, lgau, n, n, smx, im->info->nr, im->info->nc); // Locate the zero crossings printf ("Zero crossings:\n"); zero_cross (smx, im); // Clear the boundary for (i=0; i<im->info->nr; i++){ for (j=0; j<=width; j++) im->data[i][j] = 0; for (j=im->info->nc-width-1; j<im->info->nc; j++) im->data[i][j] = 0; } for (j=0; j<im->info->nc; j++){ for (i=0; i<= width; i++) im->data[i][j] = 0; for (i=im->info->nr-width-1; i<im->info->nr; i++) im->data[i][j] = 0; } free(smx[0]); free(smx); free(lgau[0]); free(lgau); }
由于高斯滤波器的宽度原因,离图像边缘小于一定值都没有被处理,局部性并不是特别好,而且边缘并不总是很细。不论如何,Marri-Hildreth边缘检测器在低信噪比的情况下要远好于传统的方法边缘检测。
[1] Theory of Edge Detection D. Marr; E. Hildreth, Proceedings of the Royal Society of London. Series B, Biological Sciences, Vol. 207, No. 1167. (Feb. 29, 1980), pp. 187-217.
关于Image Engineering & Computer Vision的更多讨论与交流,敬请关注本博和新浪微博songzi_tea.