目录
Canny的不同结果
单个2D边缘检测滤波器
实现边缘3种方法Matlab实战
第一种 图像差异
第二种 Canny边缘检测器
第三种 高斯拉普拉斯变换
Canny的不同结果
右边的图像是左边的一个边缘后的结果。
有趣的是,我的意思是,它看起来很不错,是一个很好的边缘图像。
但是我的第一个计算机视觉课程来自Berthold Horn,他是计算机视觉的创造者之一。
而且,他表达了他关心的是:很难知道什么时候图像的边缘的效果最好。
因为真正的问题是:你要用这些边缘来做什么?
我要说的是,Canny的边缘算子比其他边缘算子要更好。这意味着它们会把你想要的边缘拉出来,以便你将来处理。
当然,现在有一个问题,既然我们在做这些平滑的导数,那么我们用什么大小的高斯核来计算边缘呢?
正如我们之前说过的,不同的Sigmas,这里我们有Sigma 1, Sigma 2应用在这个小丑图像上,
你可以看到它对边缘图像做了什么:
大sigma检测大尺度图像,小sigma检测小尺度图像。
而选择取决于你想要做什么。
小测验:
Canny的边缘算子对噪声可能相当敏感。
A,正确,导数会加重噪声。
B,错误,梯度是用高斯算子的导数来计算的,它消除了噪声。
C,大部分是错的,这取决于你选择的。
答案:C。这与噪音规格相当不错,但你必须担心你选择的Sigma。
单个2D边缘检测滤波器
最后一件事要展示给你们的是完整的。
还记得高斯函数二阶导数的一维情况吗?
这是原来的高斯函数:
这个二阶导数是墨西哥帽算子:
当我们把它应用到 f 上时,这和平滑版的二阶导数是一样的:
我们在寻找那个点那些被称为零交叉的点,在底部的图上,它对应于边的位置:
但是在二维空间中做这个有点难,原因是:
求导的方向不止一个。
这里是高斯分布,公式是这样的,中间是一座漂亮的山:
但是我们必须在一个方向上求导,你知道的,下面这个图,这是x,这是1和Y:
在二阶导数上有三种选择。
我可以再次求x的偏导,所以 f² 的偏导是x的偏导的两倍。
我可以对y求偏导,两次。
我也可以求f关于y的偏导。
我应该用哪一个?
正确的答案是,你用的是高斯拉普拉斯方程。
拉普拉斯算子,就是x (f)对x²的二阶导数 加上 f (f)对y²的二阶导数:
这就是对称地给你这个墨西哥帽子操作符的原因:
如果你把它应用到图像上,取0叉乘,就会得到边。
实际上,如果你在matlab中运行一些关于边的演示代码。
你可以采取Canny边缘,或者取高斯分布的差异或者取高斯分布的拉普拉斯分布的差异,它们几乎是相同的。
你可以看到,它所做的是寻找0叉乘这是获得边的另一种方法。
其中一个挑战往往是封闭计数器,而Canny只能找到你那些有一定数量支持的轮廓。
我想告诉你们大多数人,更多的人可能会用canny来做常规的边缘检测。
三种方法画出边缘MATLAB实战
下面是MATLAB的一个快速演示,展示了几种不同的计算方法。
注意,你也可以用Octave来做。只需记住加载图像包。
好的,让我们读一个图像并显示它。
这里,我们使用figure打开一个新窗口,imshow显示窗口中的图像,title设置标题,所有这些都在一行中。
我们会经常使用这个习语。
>> %% Read Leaa image
>> lena = imread('Leana.png');
>> figure, imshow(lena), title('Original image , color');
代码运行如下:
现在我们将图像转换为单色或灰度。为此,我们将使用rgb2gray函数。
>> %% Read Leaa image
>> lena = imread('Leana.png');
>> figure, imshow(lena), title('Original image , color');
>>
>> %% Convert to monochrome (grayscale) using rgb2gray
>> lenaMono = rgb2gray(lens);
>> figure, imshow(lenaMono), title('Original image, monochrome');
这就是它的样子:
现在让我们创建一个平滑的图像版本。首先,使用fspecial函数创建一个高斯滤波器。
>> %% Make a blurred/smoothed version
>> h = fspecial('gaussian', [11 11], 4);
>> h
这是过滤器h的样子:
哇,把它画成一个平面可能会有帮助。
>> figure, suref(h);
代码显示:
现在将这个过滤器应用到图像上:
>> lenaSmooth = imfilter(lenaMono, h);
把这个和原来的比较一下:
第一种 图像差异
好的。对于第一种方法,我们将把图像左移一个像素,右一个像素,并计算它们的差异。
让我们复制一个平滑的版本来创建左边的图像。
为了将图像向左移动,我们复制所有像素,从第二列开始直到最后位置第一列到n - 1。
注意,这里的最后一列和第二列是相同的。
>> %% Method 1: Shift lef and right, and show diff image
>> lenaL = lenaSmooth;
>> lenaL(:, [1:(end - 1)]) = lenaL(:, [2:end]);
右边同样也是这么操作。
>> lenaR = lenaSmooth;
>> lenaR(:, [2:(end)]) = lenaR(:, [1:end - 1]);
现在我们计算两张图片的差异,记住转换为double类型。
注意,差异可能包含负数。
>> lenaDiff = double(lenaR) - double(lenaL);
为了正确显示它,我们传入一个空向量作为第二个参数。
>> figure, imshow(lenaDiff, []), title('Difference between right and left shifted images');
代码显示:
请注意,对象边界是如何被突出显示为较亮或较暗的区域的,这表示更大的正或负差异。
其他区域几乎是灰色的,表明接近于零的差异。
第二种 Canny边缘检测器
第二种方法是使用canny边缘检测器。
我们使用edge函数,传入'canny'作为方法参数。
>> %% Method 2: Canny edge detector
>> cannyEdges = edge(lenaMono, 'canny');
>> figure, imshow(cannyEdges), title('Edges of smoothed image');
代码结果:
还记得Canny算法执行非极大抑制吗?
这与其他一些技巧一起,产生了更有意义的边缘图像:
我们还可以在平滑的图像上运行Canny边缘检测器:
注意,现在有很多细节特性都消失了。
这是原始的边缘集,以供比较:
第三种 高斯拉普拉斯变换
我们的最后一种方法使用高斯拉普拉斯算子。
继续使用edge函数,您只需要将'log'作为方法参数传入。
%% Method 3: Laplacian of Gaussian
>> logEdges = edge(lenaMono, 'log');
>> figure, imshow(logEdges), title('Laplacian of Gaussian');
同样,Canny所发现的边缘被显示出来进行比较:
您可以使用doc edge找到更多可用的选项。
>> doc edge
代码运行结果:
如您所见,您还可以应用其他的边缘运算符,以及传入定制参数。
结语:
这就是关于边缘检测的环节的总结,事实上,目前都是关于图像处理的。
希望你们已经学了一些卷积和相关滤波的知识,以及求导的概念。
我们还讨论了过滤器被用作模板。接下来,我们要做的是我们要绕一圈,做一些真正的电脑视觉。
也就是说,计算一些数据结构告诉我们从图像中得到了什么,我们会使用这些边然后我们会回来做更多关于图像处理的事情。
但是首先,你必须要去找一些线条,圆圈,硬币和图片里的东西。非常酷。
——学会编写自己的代码,才能练出真功夫。