边缘检测学习笔记

本博客内容来源于网络以及其他书籍,结合自己学习的心得进行重编辑,因为看了很多文章不便一一标注引用,如图片文字等侵权,请告知删除。

学习笔记目录----->传送门 <-----

写在前面的废话

这是我开始写博客的第6篇了,这段时间以写博客为动力,确确实实的把一些知识又夯实了一遍。虽然写博客有的时候占用了一些工作时间,但是也相对磨炼了自己做事情的耐心,工作上也更有条理了一些。既然上篇我们描述了形态学处理,我们接着形态学处理来学习一下边缘检测吧,边缘检测也属于形态学处理的一部分。


边缘检测简介

边缘检测当然就是检测图像的上的边缘,但是什么是边缘,边缘又有何特点,接下来一一道来。

边缘就是图像上灰度或者颜色变化很大的一系列连续的点。或者说是图像上不同的区域之间的交界处。
图像中边缘的特点就要从这两方向去分析:方向和幅度。在沿着边缘走向的像素值变化比较平缓;而沿着垂直于边缘的走向,像素值则变化得比较大。

边缘检测常见方法

我们要研究边缘检测的方法,就要从它的特点入手。是否是边缘可以说是来判断一个点在某个方向上的变化是否剧烈。那么我们怎么用数学的方式去描述这种变化特点呢。在数学上,我们一般使用导数或者微分。

  • 导数: 这个很简单,就是连续函数上某点斜率,导数越大表示变化率越大,变化率越大的地方就越是“边缘”。但是,但斜率接近90度的时候,他的斜率就无限大了,在计算机计算的时候就很麻烦了,首先占用空间大,然后就是当斜率过大的时候便无法用常用的数据类型表示了。所以我们一般不用导数来表示
  • 微分: 这个概念需要在大学的时候结束,但也很简单。连续函数上x变化了dx,导致y变化了dy,dy/dx 越大,就可以表示变化率很大了。dx趋向于无限小,dy/dx 就是x在该函数上的导数,所以dy/dx就可以来近似导数,我们成这种方式叫做微分。那这种方式有什么优势呢?当我们固定dx,比较不同点的变化率时只用比较dy就好了,所以计算整幅图像的微分,dy的大小就是边缘的强弱了,我们也称之为梯度。所以我们一般会采用微分的方式。

现在我们决定是用微分的方式来判断图像上点的变化率了。那么在实际计算的时候我们算呢,我们是不是还是发现其实还是在计算一个点和周围点的关系来得出一个数值,这跟我们形态学里面说的滤波是不是一回事,对就是一回事。那么我们就可以使用滤波来完成变化率的计算了。接下里的问题就是我们采用什么样的核来进行滤波了,该怎么滤波了。下面我们来罗列一下,然后在下一节中详细解释其中一些。

算子是一个函数空间到另一个函数空间上的映射,表示的是算法中的具体计算方法或者映射方法。习惯在滤波算法使用不同的滤波核,称该算法为某某算子。

类型 具体算子
一阶边缘检测 Roberts 算子、Prewitt算子、Sobel算子 、canny算子
二阶边缘检测 Laplacian算子、Log算子/Marr算子
其他类型 Spacelk算子、Petrou算子、Susan算子、基于机器学习方法
nima,这么多,我到底该学哪个!!!

边缘检测算法详解

上面我们罗列了一些常见的边缘检测算法,下面我们详细介绍其中用的比较多的几个Roberts 算子,Prewitt算子, Sobel算子,Canny算子,Laplacian算子。

Roberts 算子

Roberts 算子是第一个边缘检测算子,由Lawrence Roberts in 1963提出,所以也比较简单,我们直接看其滤波核:

通过该滤波核,可以计算对角线上而不是坐标轴上的两个像素的微分,从而筛选边缘,选择对角线主要是因为使用标准的一阶差分,会丢失一些角点,具体分析大家可以自己举例分析一下。

Roberts算子是一个非常简单的算子,对具有低噪声的图片效果较好,但是提出的边缘比较粗,所以定位不是很准确。(效果在实现展示章节)

Prewitt算子

Prewitt算子利用像素点上下、左右的临近点的像素差来近似微分,我们直接看滤波核:

Prewitt算子有一定的抗噪能力,但这种抗噪能力使用过平均周围像素来实现的,所以对图像有一定的模糊,但是定位精度比Roberts高。

Sobel算子

和Prewitt一样,Sobel算子也是用周围8个像素来估计中心像素的梯度,但是Sobel算子认为靠近中心像素的点应该给予更高的权重,所以Sobel算子把与中心像素4邻接的像素的权重设置为2或-2。如下图:

Sobel算子相比较于Roberts算子和Prewitt算子稍好,但是并不能将图像的主体和背景区分开,所以还是有比较高的错误率。当要求不是很高的时候,这也是一个比较好的方法。(效果在实现展示章节)

Canny算子

Canny算子更是一个多步计算的方法,不像上面几种算子一次就能算出值来,我们来看一下它的计算流程。

  1. 使用高斯滤波器,以平滑图像,滤除噪声。
    • 边缘检测过程中需要检测的图片边缘属于变化比较大的信息,也称作高频信息。而图片中噪声部分也属于高频信息,因此我们需要对图像进行去噪处理,滤掉这些噪点。
  2. 计算图像中每个像素点的梯度强度和方向。
    • 计算像素梯度的幅值以及方向,常用的算子有Roberts,Sobel,计算水平及垂直方向的差分。找出梯度较大的区域,这部分区域属于图像增强的区域,此时得到的边缘信息比较粗大。
  3. 应用非极大值(Non-Maximum Suppression)抑制,以消除边缘检测带来的杂散响应。
    • 非极大值抑制主要目的是边缘细化,在梯度值比较大的地方沿着梯度方向,找到像素点的局部最大值,并将非最大值抑制(抑制就是将其弱化吧)。
  4. 应用双阈值(Double-Threshold)检测来确定真实的和潜在的边缘。
    • 所谓双阀值方法,设置一个最大阈值,以及最小阈值,梯度大于最大阈值则为强边缘,梯度值介于最大阈值与最小阈值则为弱边缘点,小于最小阈值为抑制点。这样做的目的主要是再下一步保留更多正确的边缘,删除更多错误的边缘。
  5. 通过抑制孤立的弱边缘最终完成边缘检测。
    • 这一步主要处理弱边缘点。由于边缘是连续的,因此可以认为弱边缘如果为真实边缘,就会和强边缘联通。因此通过判断是否与强边缘是否联通,是则保留为边缘,否则,认为不是边缘点。

Canny 算子是一种既能抗噪又能排除弱边缘的算子,而能能比较好的保持边缘的细节,是目前比较的好提取方法。Canny 算子提取的边缘轮廓清晰,而且封闭性好,不易受误差影响。缺点嘛,也是其他都共有的,一个就是,当边缘与背景颜色相近的时候效果不好,还有就是需要调到比较合适的参数,效果才会很好。

Laplacian算子

拉普拉斯算子是用二阶差分计算边缘的,和一阶的分析以上,就是对一阶差分的结果又做了一个一阶差分,看连续函数的情况下

  • 在一阶微分图中极大值或极小值处,认为是边缘。
  • 在二阶微分图中极大值和极小值之间的过 0 点,被认为是边缘。

    写成公式为:

    那么:

那么f ’'(x, y) = -4 f(x, y) + f(x-1, y) + f(x+1, y) + f(x, y-1) + f(x, y+1)。所以Laplacian算子是:

如果考虑上对角的情况,则是如下:

Laplacian算子对噪声也很敏感,会容易丢失一部分边缘的方向信息,造成边缘不连续。

是不是现在的你?

我们先简单介绍这么多算子,其他的我们有机会再整理成文。看了这么多,我们来看一下检测的效果。

OpenCV 边缘检测效果展示[代码]

#include <opencv2/opencv.hpp>
#include <iostream>

cv::Mat roberts(cv::Mat srcImage)
{
    cv::Mat dstImage = srcImage.clone();
    int nRows = dstImage.rows;
    int nCols = dstImage.cols;
    for (int i = 0; i < nRows - 1; i++){
        for (int j = 0; j < nCols - 1; j++){
            int t1 = (srcImage.at<uchar>(i, j) -
                srcImage.at<uchar>(i + 1, j + 1))*
                (srcImage.at<uchar>(i, j) -
                srcImage.at<uchar>(i + 1, j + 1));
            int t2 = (srcImage.at<uchar>(i+1, j) -
                srcImage.at<uchar>(i , j + 1))*
                (srcImage.at<uchar>(i+1, j) -
                srcImage.at<uchar>(i , j + 1));
            dstImage.at<uchar>(i, j) = (uchar)sqrt(t1 + t2);
        }
    }
    return dstImage;
}

int main(int argc, char *argv[])
{
    {
        cv::Mat  orignal_image = cv::imread (argv[1]);
        cv::Mat  binary_image,gray_image, roberts_edge_image,sobel_edge_image,canny_edge_image,laplacian_edge_image;
        cv::cvtColor(orignal_image, gray_image, cv::COLOR_BGR2GRAY);

        //canny
        {
            blur(gray_image, canny_edge_image, cv::Size(3, 3));
            cv::Canny(canny_edge_image, canny_edge_image, 50, 100, 3);
        }
        //sobel
        {
            cv::Mat grad_x,grad_y,abs_grad_x,abs_grad_y;
            Sobel(orignal_image, grad_x, CV_16S, 1, 0, 3, 1, 1, cv::BORDER_DEFAULT);
            convertScaleAbs(grad_x, abs_grad_x);
            Sobel(orignal_image, grad_y, CV_16S, 0, 1, 3, 1, 1, cv::BORDER_DEFAULT);
            convertScaleAbs(grad_y, abs_grad_y);
            addWeighted(abs_grad_x, 0.5, abs_grad_y, 0.5, 0, sobel_edge_image);
        }

        //laplacian
        {
            GaussianBlur(gray_image, gray_image, cv::Size(3, 3), 0, 0, cv::BORDER_DEFAULT);
            Laplacian(gray_image, laplacian_edge_image, CV_16S, 3, 1, 0, cv::BORDER_DEFAULT);
            convertScaleAbs(laplacian_edge_image, laplacian_edge_image);
        }
        //roberts
        {
           roberts_edge_image = roberts(gray_image);
        }
        cv::imwrite("roberts_edge_image.png",roberts_edge_image);
        cv::imwrite("sobel_edge_image.png",sobel_edge_image);
        cv::imwrite("canny_edge_image.png",canny_edge_image);
        cv::imwrite("laplacian_edge_image.png",laplacian_edge_image);

    }

    return 0;
}

代码解释不动了,手都写累了。。。。。。直接上一个效果吧,先贴上萌萌哒的原图
roberts sobel
canny laplacian

本片先写这么多,如果有什么不清楚的,请您评论,小生定当全力修改添加更多的配图。


重要的事情说三遍:

如果您看到我的文章对您有所帮助,那就点个赞呗 ( * ^ __ ^ * )

如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )

如果您看到我的文章对您有所帮助,那就点个赞呗( * ^ __ ^ * )

传统2D计算机视觉学习笔记目录传送门
传统3D计算机视觉学习笔记目录传送门

任何人或团体、机构全部转载或者部分转载、摘录,请保留本博客链接或标注来源。博客地址:开飞机的乔巴

作者简介:开飞机的乔巴(WeChat:zhangzheng-thu),现主要从事机器人抓取视觉系统以及三维重建等3D视觉相关方面,另外对slam以及深度学习技术也颇感兴趣,欢迎加我微信或留言交流相关工作。

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

推荐阅读更多精彩内容