【计算机视觉】 滤波器
标签(空格分隔): 【图像处理】 【Matlab开发】
说明:本系列是整理计算机视觉(英语)的笔记所成,不对之处还望指出。
##Early vision: Just one image
###linear filters
卷积,信号系统中的连续与离散卷积,还有图像处理中的卷积核,卷积神经网络等概念。对于图像处理中来讲,卷积就是卷积核来对图像进行空域滤波。有以下主要内容:
- 输出图像的每一个像素都是卷积核扫描过输入图像得到的加权平均;
- 权重保持一致;
- 窗口在像素正中。
重要的操作是:
- smoothing by averaging;
- smoothing by weighted average;
- taking a derivative。
之所以称之为线性滤波器,是因为kernel本身与图像中对应大小窗口进行的是内积。
那么直接对近邻的一些像素进行平均会导致较差的平均效果,因为可能导致ringing effects(振铃效应),距离远的neighbors与距离近的neighbor具有一样的权重、影响,这是不太科学的。那么解决方法呢:距离远的具有较小的权重、影响,距离近的具有较大的权重、影响;不妨采用高斯函数来做,于是便有了高斯卷积核,那么高斯函数有两个数字特征决定,一是均值,二是方差,在高斯卷积核中,类似的有两个概念,一是卷积模板的大小,二是尺度$\sigma$大小,$\sigma$决定陡峭程度,也就说在模板内卷积核随着原理中心的权重下降程度。
以matlab中预定义的2-Dfilters为例,fspecial,该函数实现的是输入对应的filter的名字,以及大小等参数,可以生成对应的卷积核模板
'average' averaging filter
'disk' circular averaging filter
'gaussian' Gaussian lowpass filter
'laplacian' filter approximating the 2-D Laplacian operator
'log' Laplacian of Gaussian filter
'motion' motion filter
'prewitt' Prewitt horizontal edge-emphasizing filter
'sobel' Sobel horizontal edge-emphasizing filter
'unsharp' unsharp contrast enhancement filter
比如前面说的平均滤波,使用命令:
>> filter=fspecial('average',3)
filter =
0.1111 0.1111 0.1111
0.1111 0.1111 0.1111
0.1111 0.1111 0.1111
而对于高斯卷积核:取sigma为1时对应的3x3的尺寸为:
>> filter=fspecial('gaussian',3,1)
filter =
0.0751 0.1238 0.0751
0.1238 0.2042 0.1238
0.0751 0.1238 0.0751
下面测试一下,将sigma增大一些,调为8:
>> filter=fspecial('gaussian',3,8)
filter =
0.1105 0.1114 0.1105
0.1114 0.1123 0.1114
0.1105 0.1114 0.1105
可以看到,当sigma越大,说明方差越大,方差越大说明高斯函数越分散,数据不集中,表现在卷积核上就是越来越类似于average filter了,从上面的效果也可以看出来,减噪的代价是blurring(模糊)即,方差较大的gaussian kernel其图像的细节也会随着噪声被滤掉。而当方差越小,说明高斯函数越集中,表现在卷积核上就是突出在中心的位置最大,其余几乎都是零,这说明sigma过小类似于没有做任何处理一样。比如将sigma设置为0.2为例:
>> filter=fspecial('gaussian',3,0.2)
filter =
0.0000 0.0000 0.0000
0.0000 1.0000 0.0000
0.0000 0.0000 0.0000
可以清晰的看出,卷积核只有在center的位置不为0,其余都为1。所有的卷积核模板中元素之和为1,不管是什么样的sigma,都是如此:
>> sum(sum(filter))
ans =
1
讲完了averaging,在进入到derivatives的阶段之前,在对卷积进行一下总结:
前面说的这个卷积核里面的权重weights被叫做filter kernel;
将window形状的kernel排列为vector,那么卷积实际上就是像素和filter kernel的dot-product。
filter对于在图像的window中像filter kernel的部分有较强的响应,正的响应表示just like H,而负的响应表示reversal like。那么这个filter做得到底是什么呢?细想一下,实际上filter做得是相似度的测量,即图像中某一块与该filter kernel的相似度。从这个角度上来讲,filter就是一个pattern detector,我设计好一个filter kernel,这个filter kernel代表的是一种pattern,然后我在图像中扫描,搜索哪一块儿与这个filter kernel相似度最高,也就是响应最大,也就说明图像的该块儿也就是该图像中所要找的具有该pattern的位置。但是这样有些许不足之处:是一个线性的,所以背景比较亮的patches对应的滤波器响应肯定会大,这是直接使用dot-product的弊端。采用的修改办法就是Normalized Correlation,采用计算filter kernel vector与image patches vector之间的cosine角度来作为衡量,实际上等效于做了一次normalization,normalization在机器学习中是一个非常重要的数据预处理的步骤,大家将尺度归一化。这个时候,属于响应越接近于1,image pattern就越像filter kernel,越接近-1,image pattern 越反向相似于filter kernel。
经过上面的分析可以看出,这是一种非常简单、快速且计算量像的pattern detector方法。
举个例子,如何用手势去控制两个滑块空间的移动,比如用伸开手掌左右移动,可以控制上面的滑块,握住拳头左右移动,可以控制下面的滑块。其中的道理很简单,首先得判断是手掌还是拳头,二是得判断拳头或者手掌的位置在哪里,只要实现了这两个步骤,就能实现对滑块的控制。其中的简单方法就可以使用filter kernel的方法,构造一个能代表伸开手掌的filter kernel,或者卷积模板,和一个能代表握紧拳头的filter kernel,或者卷积模板,找到摄像机捕获照片中具有最强响应的位置,超过一定的置信度,便认为是对应的拳头或手掌,于是就可以控制滑块了。【等抽空儿可以试一试,与眼动仪控制滑块进行对比一下,或者两者糅合到一起来控制】。
【说明一下,这是不是有点类似于图像的模板匹配法了,类似于直接用目标的patch作为filter kernel,然后进行扫描】
现在又有了一个问题,拳头在图像中的大小与摄像头的距离有关,这就涉及到一个尺度上的变化,如果卷积核选的大,而拳头距离较远,在图像中大小比卷积核小很多,那么就有导致错误判断的可能,所以便自然而然的引入了高斯金字塔和尺度。
resampled:较低分辨率强调的是轮廓形状,而较高分辨率强调的是细节。具体的过程是做一次高斯平滑,然后进行一次降采样,再做一次高斯平滑,再进行一次降采样,等等直到满意为止。对应到opencv的函数中对应一个resize就可以获得降采样。不同的scale,代表着different info。
A filter is a pattern of weights
Convolution applies the filter to the image
Output measures similarity between filter and image patch,only a
rough estimate
Normalized correlation gives improved pattern detection
non-linear filters
- 中值滤波
- 最大值滤波
- 最小值滤波
聊一下Local image features 首先是像素一般具有强烈的相关性,即大部分像素与它的邻居像素都比较接近,这类信息是平淡无奇的,而那些少部分不接近的,不同的,一般都是处于边界之上。这类特征,或者信息一般是我们关注的。但是噪声一般也与周围的像素不同。这些信息大部分出现在梯度较大的地方,gradient is large。所以可以使用梯度来提取这些信息,但是别忘了刚说过的噪声。那么如何先搞掉噪声呢?首先得研究一下噪声模型,下面是两个简单的噪声模型:
- 加性的高斯噪声;
- 独立同分布中得到的高斯噪声;
注意,我们在使用gradient的时候,认为是edge的是locally biggest 且 large的,不能仅仅是局部biggest,一定还要large才对。
后面又讲述了smoothed gradient:先做平滑在做gradient,或者是先做gradient后做平滑,两者的效果是一样的。
后面又专门介绍了canny 算子求edge,主要是两个点,一是非极大值抑制,二是双阈值,$K_{high}$,$K_{low}$,$K_{high}$表示找到strong edge来开启edge chain,而$K_{low}$是用来找到weak edge来连接edge chain。通常粗糙的将$K_{high}=2\times K_{low}$。
听课笔记