详解边缘检测示例

卷积运算是卷积神经网络最基本的组成部分,使用边缘检测作为入门样例。在这个博客中,会看到卷积是如何进行运算的。

在之前的博客中,说过神经网络的前几层是如何检测边缘的,然后,后面的层有可能检测到物体的部分区域,更靠后的一些层可能检测到完整的物体,这个例子中就是人脸。在这个博客中,会看到如何在一张图片中进行边缘检测。

让举个例子,给了这样一张图片,让电脑去搞清楚这张照片里有什么物体,可能做的第一件事是检测图片中的垂直边缘。比如说,在这张图片中的栏杆就对应垂直线,与此同时,这些行人的轮廓线某种程度上也是垂线,这些线是垂直边缘检测器的输出。同样,可能也想检测水平边缘,比如说这些栏杆就是很明显的水平线,它们也能被检测到,结果在这。所以如何在图像中检测这些边缘?

看一个例子,这是一个6×6的灰度图像。因为是灰度图像,所以它是6×6×1的矩阵,而不是6×6×3的,因为没有RGB三通道。为了检测图像中的垂直边缘,可以构造一个3×3矩阵。在共用习惯中,在卷积神经网络的术语中,它被称为过滤器。要构造一个3×3的过滤器,像这样\(\begin{bmatrix}1 & 0 & -1\\ 1 & 0 & -1\\ 1 & 0 & -1\end{bmatrix}\)。在论文它有时候会被称为核,而不是过滤器,但在这个博客中,将使用过滤器这个术语。对这个6×6的图像进行卷积运算,卷积运算用“\(*\)”来表示,用3×3的过滤器对其进行卷积。

关于符号表示,有一些问题,在数学中“\(*\)”就是卷积的标准标志,但是在Python中,这个标识常常被用来表示乘法或者元素乘法。所以这个“\(*\)”有多层含义,它是一个重载符号,在这个博客中,当“\(*\)”表示卷积的时候会特别说明。

这个卷积运算的输出将会是一个4×4的矩阵,可以将它看成一个4×4的图像。下面来说明是如何计算得到这个4×4矩阵的。为了计算第一个元素,在4×4左上角的那个元素,使用3×3的过滤器,将其覆盖在输入图像,如下图所示。然后进行元素乘法(element-wise products)运算,所以\(\begin{bmatrix} 3 \times 1 & 0 \times 0 & 1 \times \left(1 \right) \\ 1 \times 1 & 5 \times 0 & 8 \times \left( - 1 \right) \\ 2 \times1 & 7 \times 0 & 2 \times \left( - 1 \right) \\ \end{bmatrix} = \begin{bmatrix}3 & 0 & - 1 \\ 1 & 0 & - 8 \\ 2 & 0 & - 2 \\\end{bmatrix}\),然后将该矩阵每个元素相加得到最左上角的元素,即\(3+1+2+0+0 +0+(-1)+(-8) +(-2)=-5\)。

把这9个数加起来得到-5,当然,可以把这9个数按任何顺序相加,只是先写了第一列,然后第二列,第三列。

接下来,为了弄明白第二个元素是什么,要把蓝色的方块,向右移动一步,像这样,把这些绿色的标记去掉:

继续做同样的元素乘法,然后加起来,所以是 $0×1+5×1+7×1+1×0+8×0+2×0+2×(-1)+ 9×(-1)+5×(-1)=-4 $。

接下来也是一样,继续右移一步,把9个数的点积加起来得到0。

继续移得到8,验证一下:\(2×1+9×1+5×1+7×0+3×0+1×0+4×(-1)+ 1×(-1)+ 3×(-1)=8\)。

接下来为了得到下一行的元素,现在把蓝色块下移,现在蓝色块在这个位置:

重复进行元素乘法,然后加起来。通过这样做得到-10。再将其右移得到-2,接着是2,3。以此类推,这样计算完矩阵中的其他元素。

为了说得更清楚一点,这个-16是通过底部右下角的3×3区域得到的。

因此6×6矩阵和3×3矩阵进行卷积运算得到4×4矩阵。这些图片和过滤器是不同维度的矩阵,但左边矩阵容易被理解为一张图片,中间的这个被理解为过滤器,右边的图片可以理解为另一张图片。这个就是垂直边缘检测器。

在往下讲之前,多说一句,如果要使用编程语言实现这个运算,不同的编程语言有不同的函数,而不是用“\(*\)”来表示卷积。所以在编程练习中,会使用一个叫conv_forward的函数。如果在tensorflow下,这个函数叫tf.conv2d。在其他深度学习框架中,在后面的博客中,将会看到Keras这个框架,在这个框架下用Conv2D实现卷积运算。所有的编程框架都有一些函数来实现卷积运算。

为什么这个可以做垂直边缘检测呢?让来看另外一个例子。为了讲清楚,会用一个简单的例子。这是一个简单的6×6图像,左边的一半是10,右边一般是0。如果把它当成一个图片,左边那部分看起来是白色的,像素值10是比较亮的像素值,右边像素值比较暗,使用灰色来表示0,尽管它也可以被画成黑的。图片里,有一个特别明显的垂直边缘在图像中间,这条垂直线是从黑到白的过渡线,或者从白色到深色。

所以,当用一个3×3过滤器进行卷积运算的时候,这个3×3的过滤器可视化为下面这个样子,在左边有明亮的像素,然后有一个过渡,0在中间,然后右边是深色的。卷积运算后,得到的是右边的矩阵。如果愿意,可以通过数学运算去验证。举例来说,最左上角的元素0,就是由这个3×3块(绿色方框标记)经过元素乘积运算再求和得到的,\(10×1+10×1+10×1+10×0+10×0+10×0+10×(-1)+10×(-1)+10×(-1)=0\)

。相反这个30是由这个(红色方框标记)得到的,

\(10×1+10×1+10×1+10×0+10×0+10×0+0×(-1)+0×(-1)+ 0×(-1)=30\)。

如果把最右边的矩阵当成图像,它是这个样子。在中间有段亮一点的区域,对应检查到这个6×6图像中间的垂直边缘。这里的维数似乎有点不正确,检测到的边缘太粗了。因为在这个例子中,图片太小了。如果用一个1000×1000的图像,而不是6×6的图片,会发现其会很好地检测出图像中的垂直边缘。在这个例子中,在输出图像中间的亮处,表示在图像中间有一个特别明显的垂直边缘。从垂直边缘检测中可以得到的启发是,因为使用3×3的矩阵(过滤器),所以垂直边缘是一个3×3的区域,左边是明亮的像素,中间的并不需要考虑,右边是深色像素。在这个6×6图像的中间部分,明亮的像素在左边,深色的像素在右边,就被视为一个垂直边缘,卷积运算提供了一个方便的方法来发现图像中的垂直边缘。

神经网络之卷积篇:详解边缘检测示例(Edge detection example)的更多相关文章

  1. PHP函数篇详解十进制、二进制、八进制和十六进制转换函数说明

    PHP函数篇详解十进制.二进制.八进制和十六进制转换函数说明 作者: 字体:[增加 减小] 类型:转载   中文字符编码研究系列第一期,PHP函数篇详解十进制.二进制.八进制和十六进制互相转换函数说明 ...

  2. 走向DBA[MSSQL篇] 详解游标

    原文:走向DBA[MSSQL篇] 详解游标 前篇回顾:上一篇虫子介绍了一些不常用的数据过滤方式,本篇详细介绍下游标. 概念 简单点说游标的作用就是存储一个结果集,并根据语法将这个结果集的数据逐条处理. ...

  3. 基于双向BiLstm神经网络的中文分词详解及源码

    基于双向BiLstm神经网络的中文分词详解及源码 基于双向BiLstm神经网络的中文分词详解及源码 1 标注序列 2 训练网络 3 Viterbi算法求解最优路径 4 keras代码讲解 最后 源代码 ...

  4. Scala进阶之路-Scala函数篇详解

    Scala进阶之路-Scala函数篇详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.传值调用和传名调用 /* @author :yinzhengjie Blog:http: ...

  5. Wordpress菜单函数wp_nav_menu各参数详解及示例

    Wordpress菜单函数wp_nav_menu各参数详解及示例   注册菜单 首先要注册菜单,将以下函数添加至function.php函数里   register_nav_menus(array( ...

  6. Oracle创建表语句(Create table)语法详解及示例、、 C# 调用Oracle 存储过程返回数据集 实例

    Oracle创建表语句(Create table)语法详解及示例 2010-06-28 13:59:13|  分类: Oracle PL/SQL|字号 订阅 创建表(Create table)语法详解 ...

  7. Kubernetes K8S之affinity亲和性与反亲和性详解与示例

    Kubernetes K8S之Node节点亲和性与反亲和性以及Pod亲和性与反亲和性详解与示例 主机配置规划 服务器名称(hostname) 系统版本 配置 内网IP 外网IP(模拟) k8s-mas ...

  8. 第十五节,卷积神经网络之AlexNet网络详解(五)

    原文 ImageNet Classification with Deep ConvolutionalNeural Networks 下载地址:http://papers.nips.cc/paper/4 ...

  9. Android总结篇——Intent机制详解及示例总结

         最近在进行android开发过程中,在将 Intent传递给调用的组件并完成组件的调用时遇到点困难,并且之前对Intent的学习也是一知半解,最近特意为此拿出一些时间,对Intent部分进行 ...

  10. FFmpeg(2)-avformat_open_input()函数详解并示例打开mp4文件

    一. 解封装 pts 是显示的时间 dts是解码的时间, 这个时间是用来做同步. av_register_all(), 注册所有的格式.包括解封装格式和加封装格式. avformat_network_ ...

随机推荐

  1. 基于Web3.0的区块链图片上传

    开始前,我们先简单了解一下基本的概念,我大致归纳为以下几个点 什么是Web3.0,和区块链又有什么关系?(上回的文章不就派上用场了) 需求:开发一个基于Python的Web 3.0图片上传系统.这个系 ...

  2. vue目录文件结构

    my-vue-app/ ├── node_modules/ # 依赖的第三方模块 ├── public/ # 公共文件,不会被打包 │ ├── index.html # 应用的入口 HTML 文件 │ ...

  3. 你不知道的 CSS 之包含块

    你不知道的 CSS 之包含块 一说到 CSS 盒模型,这是很多小伙伴耳熟能详的知识,甚至有的小伙伴还能说出 border-box 和 content-box 这两种盒模型的区别. 但是一说到 CSS ...

  4. 记一次 Edge 及谷歌 Chrome 浏览器兼容性冲突的解决

    目录 记一次 Edge 及谷歌 Chrome 浏览器兼容性冲突的解决 浏览器兼容性冲突症状 解决方法 1. 把本机和远程的 8235 和 8237 端口屏蔽,包括 TCP 和 UDP 端口 2. 在 ...

  5. ClickHouse特性及底层存储原理

    ClickHouse的特性 ClickHouse是一款MPP架构的列式存储数据库,但MPP和列式存储并不是什么"稀罕"的设计.拥有类似架构的其他数据库产品也有很多,但是为什么偏偏只 ...

  6. (Java)日志框架体系整理

    # JUL 指的是Java Util Logging包,它是Java原生的日志框架,使用时不需要另外引用第三方的类库,相对其他的框架使用方便,学习简单,主要是使用在小型应用中.@紫邪情 # JUL的组 ...

  7. 请解释一下 JavaScript 的同源策略?

    概念:同源策略是客户端脚本(尤其是Netscape Navigator2.0,其目的是防止某个文档或脚本从多个不同源装载.这里的同源策略指的是:  协议,域名,端口 相同,同源策略是一种安全协议.指一 ...

  8. new操作符具体干了什么呢?

    new操作符的作用如下: 1.创建一个空对象2.由this变量引用该对象3.该对象继承该函数的原型4.把属性和方法加入到this引用的对象中5.新创建的对象由this引用,最后隐式地返回this.过程 ...

  9. Java的TimeStamp

    Java的TimeStamp 很简单,我们可以这样声明 Timestamp ts=new Timestamp(new Date().getTime());这样我们就可以得到时间比较具体的一个类型转换! ...

  10. 在Django中,多数据操作,你可以编写测试来查询另一个数据库服务器中的数据,并将结果导入当前Django项目的数据库表中

    在Django中,你可以编写测试来查询另一个数据库服务器中的数据,并将结果导入当前Django项目的数据库表中.下面是一个简单的示例: 假设你有一个Django应用程序,名为myapp,并且你希望从另 ...