第二章 基本图像处理(Image Processing)
主要内容:
- 图像的表示----介绍图像是如何表示的,以及所有基本操作的作用对象
- 高斯滤波-----滤波操作的原理与应用
- 图像金字塔-----高斯和拉普拉斯
- 边缘检测-----Sobel算子和Laplace算子
1、图像的表示
图像是由一个个的像素表示的,一个图像的像素点可以用 (x,y) 来表示位置,v来表示像素值(灰度图像的话表示一个0~255的值),因此整个图像的表示就是 {(x,y,v)} 像素点的集合。我在之前看很多图像处理的书,基本都是这样介绍的,但是CMU的课件上提出了一个我认为特别好的介绍,是把图像作为一个函数来介绍,f(x,y)=v,函数的自变量为像素点位置,函数值为像素值,画出来的函数图像如下(它把不同的像素值赋予了对应的颜色)。这个表示对后续的边缘检测、特征点获取理解帮助很大。
图像的变换基本有两个方面,一是不改变大小,改变像素点的值(即改变函数f(x,y)的值),这个操作是基于像素点的(CMU课件2.0_Point_Processing这一节对此举了不少例子 )。第二种是改变大小和像素值,这种操作一般可以改成描述为两部,第一步更改特定像素的值,第二步,在集合中删除掉部分像素点。(比如高斯图像金字塔)
2、高斯滤波
为什么需要滤波?我的理解是使图像更平滑(或者说更模糊),同时去除掉了一些噪声的干扰,为什么可以做到这样,我的理解是滤波本质上相当于把一个像素的值,跟他周围的像素值紧密联系起来,那么一个干扰点会把他的干扰分散到周围像素上,干扰强度缩小,而其本身受周围像素影响,包含了周围像素的特征,干扰强度更是大大减小,因此干扰项便不存在。
OK,CMU的课件上来讲了一个均值滤波的例子(CMU课件2.0_Box_Filter)。均值滤波的滤波器是左下这种样子的,滤波操作的公式
滤波操作的基本公式如下:h[m,n]是经过滤波操作之后,(m,n)位置处的像素值,相当于f(m+k,n+l)*g(k,l)的和,k,l是滤波器的大小,g(0,0)是中心位置。均值滤波其实就是把每个像素值,变成已它为中心,绘制1个3*3的矩形,矩形内的所有像素值的平均值。
除了均值滤波,还有中值滤波比较常见(CMU课件上没写),而且我之前应用比较多,对其颇有好感,中值滤波的原理其实根均值滤波一样,画一个矩阵,但是中值滤波中取的的是像素的中位数,这其实更适合去噪,因为我们噪声一般都是像素值比周围突出的点(这样我们人眼才能看出来他是噪声,如果隐藏在周围像素点,隐藏的比较好,那就不是噪声了),这样中值化后,它就不存在了。然后就是CMU课件中疯狂介绍的高斯滤波。
为什么是高斯滤波?首先需要明白高斯分布,高中和本科数学都学过正态分布,高斯分布其实就是正态分布,那么正态分布当初的那些性质就适合高斯分布(关于正态分布和高斯分布的介绍请移步 http://blog.csdn.net/rns521/article/details/6953591)。通过上面的介绍,其实滤波操作就是对像素进行取周围所有像素的加权和,根据经验我们知道距离该像素点越远的点对当前像素影响越小,但是无论中值滤波还是均值滤波均没考虑才到这一点,而一维高斯分布值是通过终将向两端不断减少的,二维高斯分布是向四面八方递减,那么把高斯分布作为滤波器,就可以实现不同距离的像素点的影响不同这一目的。下图左边是二维高斯分布,右边是一维高斯分布(两张图片来源于下述博客,此外关于高斯滤波的滤波矩阵推导见 http://blog.csdn.net/lonelyrains/article/details/46463987)。
那么高斯滤波有什么作用呢?CMU的课件给出了一个特别有意思的例子,就是去实现一个简单的移轴摄影,就是怎么样把左边的图像变成右边的图像。其实很简单,把第二幅图像中跟第一幅图像一样清晰的像素块取出来,加上第一幅图像中剩余的像素点,做一次高斯滤波。
课件上给出的解决方案:
3、图像金字塔
提出图像金字塔的主要目的是为了压缩图像。比如把一个图像压缩到1/2,可以怎么办?
高斯金字塔解决方案:1、将原图做一次高斯滤波 2、把做完高斯滤波图像的所有偶数行列全去掉。
整个方法看上去很不错,但是存在一个问题,怎么还原?我们先复原大小(位置值先用0表示,然后再做一次类似逆滤波的操作),但是这个时候还原回去之后,数据会存在误差。Laplacian金字塔就是把误差保存下来——其实是每次高斯滤波之后丢弃的数据。用代码去实现整个压缩过程如下:
for i from 0 to sacle:
li=blur(fi) #对图像fi做一次滤波
hi=li-fi #保存丢失信息,Laplacian金字塔
fi+1=subSample(li) #更改图像大小 ######复原代码
for i for scale to 0:
li=unSample(fi) #大小复原
fi+1=li+hi #加上误差
4、边缘检测
什么是边缘?从图像上来说是像素值的分解线,从第一小节中的二维函数图像中来看,就是周围函数值发生突然变化的像素点就是边缘。这样目的就明确了,找到附近函数值变化比较大的点,高中学的导数的定义就是函数的变化率,导数大的地方函数值变化大。问题在于图像函数是无法用表达式表达出来,因此不能用既定的求导公式去计算,在高等数学的极限和中学数学中,我们学过用下面这个公示去近似导数
CMU的课件(4.0_Image_Gradients_And_Gradient_Filtering)中列出了下面的一个例子,假设下面这一行数据是某个图像中的x方向一行的像素值,利用近似导数的方法求某个像素点附件的x导数,其实相当于乘以了右侧的过滤器。假设成了多个过滤器,即跟X在同一列上的相邻像素的近似梯度值,这样,如果这个梯度值比较大,其实就相当于这块有一条近似垂直的边界线(y方向)。
图像都是二维的,因此求x方向梯度值大的求出来都是近似垂直的边界,同时需要再利用同样的方法在求一遍y方向的梯度值变化,最后把梯度值转换成灰度值。这就是Sobel算子的原理
在CMU的课件中,还提到了一点,当然也是实际应用中非常重要的一点,Sobel算子对噪声比教敏感,因此需要在处理之前进行去噪(高斯滤波等)。
在介绍完Sobel算子之后,CMU的课件又介绍了Laplace过滤器。Laplace的原理在于求像素点的二阶导数(实际上是二阶梯度,表达式没有,二阶导数求不出来o(╯□╰)o),二阶导数是对一阶导数求导的结果,二阶导数为0,意味着一阶导数再次取到了极值,一阶导数表示灰度值的变换情况,一阶导数取到了极值,也就是说原图在此灰度值变换巨大。下图是截取自CMU课件中关于Laplace过滤器推倒的过程。
下面这张图展示了图像经过Sobel算子和Laplace过滤器之后的不同,可以看到利用Laplace过滤器的中间为0的这个特性,可以更好的定位边缘。
第二章 基本图像处理(Image Processing)的更多相关文章
- 学习opencv中文版教程——第二章
学习opencv中文版教程——第二章 所有案例,跑起来~~~然而并没有都跑起来...我只把我能跑的都尽量跑了,毕竟看书还是很生硬,能运行能出结果,才比较好. 越着急,心越慌,越是着急,越要慢,越是陌生 ...
- 第二章 Qt常用工具的介绍
第二章 Qt常用工具的介绍 (1)No.1 qmake 相信编写过Makefile的开发人员,随着工程中源码的级数递增和以类型.功能.模块组织源码的子目录的增多,都不愿意重复机械地手工编写这个工程管理 ...
- Python3-Cookbook总结 - 第二章:字符串和文本
第二章:字符串和文本 几乎所有有用的程序都会涉及到某些文本处理,不管是解析数据还是产生输出. 这一章将重点关注文本的操作处理,比如提取字符串,搜索,替换以及解析等. 大部分的问题都能简单的调用字符串的 ...
- C# Language Specification 5.0 (翻译)第二章 词法结构
程序 C# 程序(program)由至少一个源文件(source files)组成,其正式称谓为编译单元(compilation units)[1].每个源文件都是有序的 Unicode 字符序列.源 ...
- 《细说PHP》第四版 样章 第二章 PHP的应用与发展 1
<细说PHP>第四版 样章 第二章 PHP的应用与发展 1 学习任何编程语言之前,先了解一下它的应用与发展是很有必要的.从Web开发的历史看来,PHP.Python和Ruby几乎是同时出现 ...
- ASP.NET MVC with Entity Framework and CSS一书翻译系列文章之第二章:利用模型类创建视图、控制器和数据库
在这一章中,我们将直接进入项目,并且为产品和分类添加一些基本的模型类.我们将在Entity Framework的代码优先模式下,利用这些模型类创建一个数据库.我们还将学习如何在代码中创建数据库上下文类 ...
- 《Django By Example》第二章 中文 翻译 (个人学习,渣翻)
书籍出处:https://www.packtpub.com/web-development/django-example 原作者:Antonio Melé (译者注:翻译完第一章后,发现翻译第二章的速 ...
- Jenkins入门系列之——02第二章 Jenkins安装与配置
2014-12-08:已不再担任SCM和CI的职位,Jenkins的文章如无必要不会再维护. 写的我想吐血,累死了. 网页看着不爽的,自己去下载PDF.有问题请留言! Jenkins入门系列之——03 ...
- Python黑帽编程 2.0 第二章概述
Python黑帽编程 2.0 第二章概述 于 20世纪80年代末,Guido van Rossum发明了Python,初衷据说是为了打发圣诞节的无趣,1991年首次发布,是ABC语言的继承,同时也是一 ...
随机推荐
- Java 垃圾回收(GC) 泛读
Java 垃圾回收(GC) 泛读 文章地址:https://segmentfault.com/a/1190000008922319 0. 序言 带着问题去看待 垃圾回收(GC) 会比较好,一般来说主要 ...
- C#研究OpenXML之路(4-使用第三方库)
一.悲催的OpenXML操作 学习并使用了一段时间的OpenXML,感觉用这个来操作Excel文件真是一件非常悲催的事情,由于我自己比较熟悉Excel COM的操作,但到了OpenXML中发现,之前所 ...
- C#研究OpenXML之路(2-DocumentFormat.OpenXml命名空间)
一.OpenXML对象结构预览 昨天感受了一下OpenXML的编程,今天开始准备一头扎进OpenXML了.在了解一门新的知识前,首先最重要的是理清逻辑结构,否则学习起来会感觉摸不着北. 1.首先打开V ...
- 细细探究MySQL Group Replicaiton — 配置维护故障处理全集
本文主要描述 MySQL Group Replication的简易原理.搭建过程以及故障维护管理内容.由于是新技术,未在生产环境使用过,本文均是虚拟机测试,可能存在考虑不周跟思路有误 ...
- 浩哥解析MyBatis源码(七)——DataSource数据源模块之托管数据源
原创作品,可以转载,但是请标注出处地址:http://www.cnblogs.com/V1haoge/p/6675700.html 1 回顾 之前介绍的非池型与池型数据源都是MyBatis自己定义的内 ...
- 设计模式(二)—工厂方法模式
凡是出现了大量的实例需要创建,而且具有共同的接口时,可以通过工厂方法模式进行创建. 一个接口: Sender public interface Sender{ public void sen ...
- Jackson序列化实例
参考文章 Jackson使用ContextualSerializer在序列化时获取字段注解的属性 使用BeanSerializerModifier定制jackson的自定义序列化(null值的处理) ...
- Servlet(一)基础总结
一.Servlet概述 1.Java Servlet是基于Java的一种技术和标准,是独立于平台和协议,服务器端的java应用程序.与Applet相比.Applet运行在客户端,而Servlet运行在 ...
- libev事件库使用笔记
源码下载地址:http://dist.schmorp.de/libev/ libev是一个高性能的事件循环库,比libevent库的性能要好. 安装: tar -zxf libev-4.15.tar. ...
- 复选框选中删除行(DOM练习)
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" ...