文档章节

翻译:计算机视觉中的边缘检测

FreeBlues
 FreeBlues
发布于 2016/08/01 11:41
字数 3016
阅读 225
收藏 5

翻译:计算机视觉中的边缘检测

翻译自: Edge Detection in Computer Vision

概述

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

截图1:

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

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

截图2:

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

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

边缘检测:滤波

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

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

截图3:

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

边缘检测:高斯滤波器

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

截图4:

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

  • 我的猫 Mew 的图片

截图5:

  • 对我的猫 Mew 的图片应用高斯滤波

截图6:

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

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

截图7:

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

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

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

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

边缘检测:应用滤波器

我们已经有了两个高斯滤波器,我们把他们应用到图像中。我们同样使用非极大值限制,即如果不是极大值的话,就把像素值设置为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);

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

  • 基本边缘滤波器: 对我的猫的黑白图片应用滤波器

截图8:

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

  • 基本边缘滤波器: 对我的猫的RGB图片应用滤波器

截图9:

这两张图片应该都能代表像素和它相邻之间像素的颜色的差异,只不过彩色图像有3个通道:RGB,而黑白图像只有1个通道。(原译文翻译为层, 这里改为通道)

边缘检测:方向滤波器

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

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

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

截图10:

顶部行x分量,底部行y分量

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

截图11:

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

% 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);

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

截图12:

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

边缘检测:提高彩色域

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

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

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

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

截图13:

事实上,这些颜色通道非常适合发现颜色变化梯度,正如自然而然地黄色很少出现另一个黄色周围,红色和绿色也是如此。(尽管我已经彻底证明了)。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空间图像

截图14:

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

  • Lab 彩色域上边缘检测

截图15:

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

  • Lab 彩色域边缘检测

截图16:

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

截图17:

边缘检测:结语

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

我使用这些方法解释它是因为我对它们很有兴趣。。。加上这是 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

参考文献

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

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.

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

本文转载自:http://blog.csdn.net/yewei11/article/details/50748012

共有 人打赏支持
FreeBlues
粉丝 98
博文 280
码字总数 493678
作品 0
其它
程序员
私信 提问
计算机视觉计算任务有哪些,怎么分类 ?

计算机视觉计算任务有哪些,怎么分类 ? 我把任务分为像素级别、目标级别、理解级别。 像素级别的任务一般是传统的图像处理任务,他们不需要用到图像的语义信息,或者最多用到底层特征(比如图...

Terminator2050
2018/08/27
0
0
为什么深度学习没有取代传统的计算机视觉?

这篇文章是受到论坛中经常出现的问题所创作的: 深度学习是否可以取代传统的计算机视觉? 这明显是一个很好的问题,深度学习(DL)已经彻底改变了计算机视觉(CV)和人工智能。许多曾经看起来...

【方向】
2018/03/15
0
0
借助 OpenCV 找到车载记录仪中的车道线

雷锋网按:本文为 AI 研习社编译的技术博客,原标题 Finding Driving Lane Line live with OpenCV,作者为 Percy Jaiswal。 翻译 | 尘央 王飞 校对 | 余杭 整理 | MY 大家好!在此项目中,我...

雷锋字幕组
2018/08/16
0
0
吴恩达【深度学习工程师】学习笔记(十一)

吴恩达【深度学习工程师】专项课程包含以下五门课程: 1、神经网络和深度学习; 2、改善深层神经网络:超参数调试、正则化以及优化; 3、结构化机器学习项目; 4、卷积神经网络; 5、序列模型...

zchang81
2018/01/17
0
0
opencv动态边缘检测-python

OpenCV:是一个基于BSD许可(开源)发行的跨平台计算视觉库。由一系列C函数和少量的C++编写,实现图像处理和计算机视觉方面的很多通用算法。 Canny边缘检测算子:是一种多级检测算法。1986年...

yan_shichang
2018/04/24
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Java单例模式学习记录

在项目开发中经常能遇见的设计模式就是单例模式了,而实现的方式最常见的有两种:饿汉和饱汉(懒汉)。由于日常接触较多而研究的不够深入,导致面试的时候被询问到后有点没底,这里记录一下学习...

JerryLin123
昨天
1
0
VSCODE 无法调试

VSCODE 无法调试 可以运行 可能的原因: GCC 的参数忘了加 -g

shzwork
昨天
3
0
理解去中心化 稳定币 DAI

随着摩根大通推出JPM Coin 稳定币,可以预见稳定币将成为区块链落地的一大助推器。 坦白来讲,对于一个程序员的我来讲(不懂一点专业经济和金融),理解DAI的机制,真的有一点复杂。耐心看完...

Tiny熊
昨天
4
0
5.线程实现

用于线程实现的Python模块 Python线程有时称为轻量级进程,因为线程比进程占用的内存少得多。 线程允许一次执行多个任务。 在Python中,以下两个模块在一个程序中实现线程 - _thread 模块 th...

Eappo_Geng
昨天
3
0
ServiceLoader

创建一个接口文件在resources资源目录下创建META-INF/services文件夹在services文件夹中创建文件,以接口全名命名创建接口实现类 内容me.zzp.ar.d.PostgreSQLDialectme.zzp.ar.d.Hype...

Cobbage
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部