计算机视觉中的边缘检测

边缘检测是计算机视觉中最重要的概念之一。这是一个很直观的概念,在一个图像上运行图像检测应该只输出边缘,与素描比较相似。我的目
标不仅是清晰地解释边缘检测是怎样工作的,同时也提供一个新而又容易的方法只需要最小工作来明显地提高边缘检测。

通过获得这些边缘,许多计算机算法才得以有可能实现,因为在一个场景中边缘包含着绝大部分(至少很多)的信息。

举个例子,我们都记得 Windows XP 的那个绿色小山坡和蓝色天空的背景。



当我们的大脑试图去理解这个场景时,我们知道这是草地,看起来很统一。然后,我们看到了飘着些许白云的天空。这些对象的每一个都是分离的,而且它们之间有一个边缘。这就是场景中为什么绝大部分的信息存在与边缘中。

这也是为什么边缘检测是计算机视觉中的重要概念。通过把图像减少到只剩下边缘,使得对于许多算法更容易识别、学习、或者处理场景。

边缘检测:滤波

边缘检测的大多数是基于滤波的。通常来说,滤波是一个消除的动作。比如:过滤水,是消除寄生虫。相似地,当我们尝试找到图像边缘时,我是在尝试消除掉除图像边缘之外的东西。

消除那些不是有用的边缘的图像部分,而留下合适的边缘也是困难所在。我怎么知道这是不是有用的边缘,比如,我对 Windows XP 背景运行 Canny edge dectector 程序,效果如下。

你能看到那些小草的细小刀刃似的边缘,这很让人讨厌,而且没有真正提供有用的信息。甚至那些云朵也不是非常清晰。现在,你能在大多数的 Canny edge dectector 上设置一些边界,这些边界设置了阈值(或者 非极大值抑制),所有的边缘必须满足这个阈值才能划分为“重要的”边缘。与其在 Canny edge 的阈值上区分,不如我们更广泛地来谈谈,并且搭建几个滤波器。

边缘检测:高斯滤波器

高斯滤波器是边缘检测最基础的滤波器之一,虽然还有其他的,但是高斯滤波器会贯穿这篇文章。高斯滤波器,正如其名,是一个基于高斯分布的滤波器。

它看起来像一个抛物线(除了在二维的情况)。通过矩阵乘法,高斯滤波器能被应用到每一个像素上。它实现的是混合效果,让最中心的像素尽量小基于它相邻的像素。举个例子,如对我的猫的图像运行一个均匀分布的高斯滤波器,我能够得到下面的图像:

5.jpg

你可以看到图像变得模糊了,高斯滤波器就是获取所有像素,让像素值的成分是与相邻像素有关。

为了让高斯滤波器在边缘检测中有效,我们可以使用从 x 和 y 方面求导出来的高斯滤波器。这也许听起来有点反直觉,或者不知所谓,但是如果我们看到这种导数高斯滤波器的图像,这种想法就很清晰了。

当你把一个高斯的 x 和 y 分量求导后,一个大的波峰 和波谷就出现了。如果你明白导数,思考下这种情况,你应该能很快想到。由于高斯函数峰上数值上的巨大变化,从而导致了高斯导数波峰和波谷的出现。

如果我们把上面的写成代码,那相当直接(至少对于 Matlab 和 Python 来说):

% Takes the derivative of a 5x5 gaussian, with a sigma    
[hx, hy] = gradient(fspecial('gaussian',[5 5],sigma));

这就是了,一行代码就能得到我们所想要的高斯,然后对x 和 y 分量求导。

边缘检测:应用滤波器

我们已经有了两个高斯滤波器,我们把他们应用到图像中。我们同样使用非极大值限制,即如果不是极大值的话,就把像素值设置为0。换种说法就是消除噪声。

应用滤波器的代码如下:

% Convert an image to double for increased precision
img = double(img);
% Find two derived gaussians with respect to x and y
[hx, hy] = gradient(fspecial('gaussian',[5 5],sigma));
% Run the filters over the image, generating a filtered image
% Leaves x edges
gx = double(imfilter(img,hx,'replicate', 'conv'));
% Leaves y edges
gy = double(imfilter(img,hy,'replicate', 'conv'));
% Take the absolute value, and combine the x and y edges
mag = sqrt((gx .* gx) + (gy .* gy));
% Use non-maxima suppression 
[mag, ] = max(mag, [], 3);

如果我们将它应用我的猫的一张图片,我我们就得到一下的图片:

有趣地是,我们同样也能这种方法应用到 RGB 图像上去,同样也会得到彩色的边缘。

普通的边缘滤波器应用到猫的RGB图像

这两张图片应该都能代表像素和它相邻之间像素的颜色的差异,只不过彩色图像有3层,而黑白图像只有1层。(层,翻译不是很好)

边缘检测:方向滤波器

为什么要限制我们自己仅仅使用绝对的 x 和 y 方向的滤波器呢?让我们也来构建一些方向滤波器。这个方法(或多或少)来源于 Freeman 和 Adelson 的《The design and use of steerable filters》论文,这个想法使我们能够把我们的高斯滤波器放置在不同的方向。

根本上,我们把我们的高斯滤波器放置到不同的方向上去,以基于与高斯相关的边缘的角度来创建不同数值。比如,如果我们把高斯函数放置到45度,应用到45度角的图像上,应该可以比在0度的高斯函数得到更高的数量级。

在这种情况下,我生成了几种不同的方向滤波器:

上行x分量,下行y分量

各种各样的高斯函数产生了相对于x 和 y 分量上的90、45、-45 和 22.5 度的滤波器。这也就产生了不同的边缘大小,尽管这些滤波器应该检测出相近的边缘。

我使用的代码与单个滤波器使用的代码几乎相同,但是我不同以往地把他们混合在一起。它看起来有点杂乱,但是我通过让我运行每个滤波器表达更明白来尽可能使它看起来更清晰。

% Create four filters
[hx, hy] = gradient(fspecial('gaussian',[5 5],sigma));
[hx1, hy1] = altOrientFilter1(hx, hy);
[hx2, hy2] = altOrientFilter2(hx, hy);
[hx3, hy3] = altOrientFilter3(hx, hy);

% Run first gaussian filter on image
gx = double(imfilter(img,hx,'replicate', 'conv'));
gy = double(imfilter(img,hy,'replicate', 'conv'));
% Run second gaussian filter on image
gx1 = double(imfilter(img,hx1,'replicate', 'conv'));
gy1 = double(imfilter(img,hy1,'replicate', 'conv'));
% Run third gaussian filter on image
gx2 = double(imfilter(img,hx2,'replicate', 'conv'));
gy2 = double(imfilter(img,hy2,'replicate', 'conv'));
% Run fourth gaussian filter on image
gx3 = double(imfilter(img,hx3,'replicate', 'conv'));
gy3 = double(imfilter(img,hy3,'replicate', 'conv'));

% Merge all filters
squareGD = (gx .* gx) + (gy .* gy);
squareGD = squareGD + (gx1 .* gx1) + (gy1 .* gy1);
squareGD = squareGD + (gx2 .* gx2) + (gy2 .* gy2);
squareGD = squareGD + (gx3 .* gx3) + (gy3 .* gy3);

% Run non-maxima supression
[mag, ] = max(sqrt(squareGD), [], 3);

如果你靠近点看的话,你能看到数量大小的不同,特别是那些皱纹。如果我们混合了所有图像,我们就能得到一张轻微较好的边缘检测。

方向滤波器和非方向滤波器之间并没有很大的不同,但是我们也应该看到多种方向的结果有些许的提高。

边缘检测:提高彩色域

过去两年,我在不同的彩色域上做了大量的测试和实验。特别地是,Lab 彩色域是另一种描述图像的方式。比如,我们知道的RGB 和灰度图像,或者你甚至可能知道YUV空间。 Lab 彩色域与之非常相似。

我对Lab 彩色感兴趣的原因是它对产生场景的边缘有着优异的能力。

Lab 彩色空间的每个字母表示:

  • L —— Luminance亮度
  • a —— alpha —— 红到绿
  • b —— beta —— 黄到蓝

事实上,这些颜色通道非常适合发现颜色变化梯度,正自然而然地黄色很少出现另一个黄色周围,红色和绿色也是如此。(尽管我已经彻底证明了)。Lab 彩色空间与我们人类怎样察觉颜色中的亮度有很强的相关性。与RGB相反的是,在Lab 彩色空间中亮度有它自己的分离通道,这使得它能更好地处理颜色的差异,这些差异也是亮度与颜色相关之处。

为了最小化额外的代码,我们所要做的就是把输入的图像转化为Lab彩色空间的图像。你可以做一些最优化,不过你仅仅做了这额外的一步也能明显提高适宜的边缘检测。

% Convert an image to the Lab color space
colorTransform = makecform('srgb2lab');
img = applycform(rgbImg, colorTransform);

% Make it double to improve representation
img = double(img);

% Find x and y derivative of a 9x9 gaussian
[hx, hy] = gradient(fspecial('gaussian',[9 9],sigma));

% Apply filters    
gx = double(imfilter(img,hx,'replicate'));
gy = double(imfilter(img,hy,'replicate'));

% Find absolute value
gSquared = sqrt(gx .* gx) + (gy .* gy);

% Apply non-maxima suppression (find best points for edges) 
[mag, ] = max(gSquared, [], 3);

如果我们将 Windows XP 小山坡的背景图像转换为Lab,我们将得到下面的图像:

Windows XP 背景的Lab空间图像

然后如果我们施加滤波器(非极大值抑制)将得到下面的图像,清晰的包含着草地、云、草地和天空的分界线的图象。

在Lab 空间上边缘检测

最终,如果我们运行非极大值抑制,那么我们将得到比本文开头提到的 Canny边缘检测器要好得多的边缘效果。

Lab 彩色空间边缘检测

平均来说,这种方法会比普通方法提高 10% 左右的边缘检测精度。这是对 The Berkeley Segmentation Dataset and Benchmark 运行 F-measure 测试得到的结果。

边缘检测:结语

有无数的方法去做边缘检测,这里讲述的方法绝不是最好、最容易实现、最容易解释的。

我使用这些方法解释它是因为我对它们很有兴趣。。。加上这是 UIUC的CS543课程《计算机视觉》布置的作业,所以你也在上这门课,请不要抄袭我的代码!

我已经把我们所有的实现都放到了 github 上了。包括用 C++ 的 OpenCV 实现。

然而,如果你想跟我的猫照相,这没什么问题。

建议阅读

  • PCA: Principal Component Analysis
  • Everyday Algorithms: Pancake Sort
  • Using Computer Vision to Improve EEG Signals
  • Introduction to Markov Processes
  • The Cache and Multithreading

参考文献

[1] Canny, John. “A computational approach to edge detection.” Pattern Analysis and Machine Intelligence, IEEE Transactions on 6 (1986): 679-698.

[2] Freeman, William T., and Edward H. Adelson. “The design and use of steerable filters.” IEEE Transactions on Pattern analysis and machine intelligence 13.9 (1991): 891-906.


这是本人课余时间的翻译,如有错误,还请耐心指出,谢谢!
原文链接请点击原文链接

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,482评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,377评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,762评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,273评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,289评论 5 373
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,046评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,351评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,988评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,476评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,948评论 2 324
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,064评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,712评论 4 323
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,261评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,264评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,486评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,511评论 2 354
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,802评论 2 345

推荐阅读更多精彩内容