17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列


本文作者:小嗷

微信公众号:aoxiaoji

吹比QQ群:736854977

微信链接:https://mp.weixin.qq.com/s?__biz=MzU1MTgxNjQyMg==&mid=2247483823&idx=1&sn=95bacfb534aea99476024c127a30d8b0&chksm=fb8adc26ccfd55308415cf022384dbf3d176c48a82f7950047b797e53881e89793572c2b0ce9#rd


image

这部分就开始讲图像处理模块,

即需要导入imgproc这个库(java叫包)

我也相信以这种速度,很快就讲

到物体识别。

计划:2篇QT + 3篇OpenCV(7天5篇)

当然,这是理想的情况。

.......

滤波器可以说是信号处理中最重要的研究对象,滤波器可以将原始信号的有用信息通过各种组合来凸显出来,因此很多时候也将它们称为Neighborhood operators,基本上所有涉及到特征的应用场合都要考虑滤波器,即使是发展到看起来很高大上的深度学习等,各种滤波器如果设计的好的话,能够极大地提高整个算法的准确度和效率。

image

在本文中,您将学习如何应用不同的线性过滤器来使用OpenCV函数来平滑图像,例如:

  1. 线性运算

  2. 卷积

在图像处理中,对邻域中的像素的计算为线性运算时,如利用窗口函数进行平滑加权求和的运算,或者某种卷积运算,都可以称为线性滤波。常见的线性滤波有:均值滤波、高斯滤波、盒子滤波、拉普拉斯滤波等等,通常线性滤波器之间只是模版系数不同。

线性运算是加法和数量乘法, 在实数领域像只包含加法和数量乘法二元一次方程就属于线性运算,如y=3x+5。如果是矩阵的加法和数乘运算,就称为矩阵的线性运算;如果是向量的加法和数乘运算,统称为向量的线性运算。对于不同线性运算一般有不同的形式,它们满足交换律、结合律、分配律等。

2.1 这里我们重点讲矩阵的线性运算(其实图像就是个矩阵)

矩阵的加法和数乘运算,统称为矩阵的线性运算。

矩阵加减法,定义 设

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第1张图片
image

是两个m x n型矩阵,则矩阵

image

称为A和B的和,记为

image

注意:图像RGB的时候范围0-255,一般我们都会saturate_cast函数(value)确保值大小范围为0~255之间。

详情内容在第八篇对比度和亮度代码使用过,而对像素点操作最快的相关代码在第十篇里面,两者可以结合起来。

矩阵的加法就是矩阵对应元素相加,当然,相加的矩阵必须要有相同的行数和列数,即只有同型矩阵方可相加。

由于矩阵加法归结为它们元素的加法,即数的加法,故不难验证矩阵加法满足:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第2张图片
image

减乘除同理,不懂的话call我,如果多人不懂就在写写

2.2 卷积运算

小嗷没学过线性代数一开始都不懂,就算学过也忘了。最后,也是看免费的网易公开课理解,算是比较系统理解。(网址在上篇有)

至于最近大火的深度学习,更有专门的卷积神经网络(Convolutional Neural Network, CNN),在图像领域取得了非常好的实际效果,已经把传统的图像处理的方法快干趴下了。(但是,就现在而言,搞深度学习基本都是亏。论文易,产品难)

卷积运算是指从图像的左上角开始,开一个与模板同样大小的活动窗口,窗口图像与模板像元对应起来相乘再相加,并用计算结果代替窗口中心的像元亮度值。然后,活动窗口向右移动一列,并作同样的运算。以此类推,从左到右、从上到下,即可得到一幅新图像。

瞄了一眼,知乎某些数学大神,有很好的解释(当然,小嗷是个数学渣渣,也会加上自己初高中水平的看法)

这个其实非常简单的概念,国内的大多数教材却没有讲透。

直接看图,不信看不懂。以离散信号为例,连续信号同理。

已知x[0] = a, x[1] = b, x[2]=c

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第3张图片
image

已知y[0] = i, y[1] = j, y[2]=k

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第4张图片
image

下面通过演示求x[n] * y[n]的过程,揭示卷积的物理意义。

第一步,x[n]乘以y[0]并平移到位置0:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第5张图片
image

(ai=1x2=2,bi=3x2=6,ci=2x2=4)
第二步,x[n]乘以y[1]并平移到位置1

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第6张图片
image

上面同理

第三步,x[n]乘以y[2]并平移到位置2:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第7张图片
image

上面同理

最后,把上面三个图叠加,就得到了x[n] * y[n]:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第8张图片
image

(三个图加起来的结果图,不难。不懂就仔细看,ths)

简单吧?无非是平移(没有反褶!)、叠加。 从这里,可以看到卷积的重要的物理意义是:一个函数(如:单位响应)在另一个函数(如:输入信号)上的加权叠加。

重复一遍,这就是卷积的意义:加权叠加。

对于线性时不变系统,如果知道该系统的单位响应,那么将单位响应和输入信号求卷积,就相当于把输入信号的各个时间点的单位响应 加权叠加,就直接得到了输出信号。

通俗的说: 在输入信号的每个位置,叠加一个单位响应,就得到了输出信号。 这正是单位响应是如此重要的原因。

在输入信号的每个位置,叠加一个单位响应,就得到了输出信号。 这正是单位响应是如此重要的原因。

在输入信号的每个位置,叠加一个单位响应,就得到了输出信号。 这正是单位响应是如此重要的原因。

以上是知乎上排名最高的回答。比较简单易懂。

有个回复也可以参考: 楼主这种做法和通常教材上的区别在于:书上先反褶再平移,把输入信号当作一个整体,一次算出一个时间点的响应值;而楼主把信号拆开,一次算出一个信号在所有时间的响应值,再把各个信号相加。两者本质上是相同的。

2.3 卷积的另外解释

小嗷认为看懂就看,看不懂就算了,不然你买本信号与系统自己看几百页纸吧,开个玩笑。

卷积表示为y(n)=x(n)∗h(n)

使用离散数列来理解卷积会更形象一点,我们把y(n)的序列表示成y(0),y(1),y(2),⋯y(0),y(1),y(2),⋯, 这是系统响应出来的信号。

同理,x(n)的对应时刻的序列为x(0),x(1),x(2),⋯x(0),x(1),x(2),⋯

其实我们如果没有学过信号与系统,就常识来讲,系统的响应不仅与当前时刻系统的输入有关,也跟之前若干时刻的输入有关,因为我们可以理解为这是之前时刻的输入信号经过一种过程(这种过程可以是递减,削弱,或其他)对现在时刻系统输出的影响,那么显然,我们计算系统输出时就必须考虑现在时刻的信号输入的响应以及之前若干时刻信号输入的响应之“残留”影响的一个叠加效果。

假设0时刻系统响应为y(0),若其在1时刻时,此种响应未改变,则1时刻的响应就变成了y(0)+y(1),叫序列的累加和(与序列的和不一样)。但常常系统中不是这样的,因为0时刻的响应不太可能在1时刻仍旧未变化,那么怎么表述这种变化呢,就通过h(t)这个响应函数与x(0)相乘来表述,表述为x(m)×h(m−n),具体表达式不用多管,只要记着有大概这种关系,引入这个函数就能够表述y(0)在1时刻究竟削弱了多少,然后削弱后的值才是y(0)在1时刻的真实值,再通过累加和运算,才得到真实的系统响应。

再拓展点,某时刻的系统响应往往不一定是由当前时刻和前一时刻这两个响应决定的,也可能是再加上前前时刻,前前前时刻,前前前前时刻,等等,那么怎么约束这个范围呢,就是通过对h(n)这个函数在表达式中变化后的h(m−n)中的m的范围来约束的。即说白了,就是当前时刻的系统响应与多少个之前时刻的响应的“残留影响”有关。

当考虑这些因素后,就可以描述成一个系统响应了,而这些因素通过一个表达式(卷积)即描述出来不得不说是数学的巧妙和迷人之处了。

2.4 卷积的数学定义

前面讲了这么多,我们看看教科书上对卷积的数学定义。


17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第9张图片
image

2.5 卷积的应用

用一个模板和一幅图像进行卷积,对于图像上的一个点,让模板的原点和该点重合,然后模板上的点和图像上对应的点相乘,然后各点的积相加,就得到了该点的卷积值。对图像上的每个点都这样处理。由于大多数模板都是对称的,所以模板不旋转。卷积是一种积分运算,用来求两个曲线重叠区域面积。可以看作加权求和,可以用来消除噪声、特征增强。

如:邻域滤波(卷积)

邻域算子值利用给定像素周围像素的值决定此像素的最终输出。如图左边图像与中间图像卷积等于右边图像。目标图像中绿色的像素由原图像中蓝色标记的像素计算得到。

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第10张图片
image

通用线性邻域滤波是一种常用的邻域算子,输入像素加权得到输出像素:

image

65 x 0.1+98 x 0.1+123 x 0.1+65 x 0.1+96 x 0.2 + 115 x0.1 + 63 x 0.1 + 91 x 0.1 + 107 x 0.1 = 91.9约等于92(不知道我有没有算错,算错告诉小嗷公众号或者QQ什么回一声,谢谢)

卷积是一种线性运算,图像处理中常见的mask运算都是卷积,广泛应用于图像滤波。

卷积关系最重要的一种情况,就是在信号与线性系统或数字信号处理中的卷积定理。利用该定理,可以将时间域或空间域中的卷积运算等价为频率域的相乘运算,从而利用FFT等快速算法,实现有效的计算,节省运算代价。

2.6 补充(又是卷积)

另外在知乎上看到非常好也非常生动形象的解释,特意复制粘贴过来。(知乎马同学的解释)

从数学上讲,卷积就是一种运算。

某种运算,能被定义出来,至少有以下特征:

1.首先是抽象的、符号化的

2.其次,在生活、科研中,有着广泛的作用

比如加法:

1.a+b,是抽象的,本身只是一个数学符号

2.在现实中,有非常多的意义,比如增加、合成、旋转等等

卷积,是我们学习高等数学之后,新接触的一种运算,因为涉及到积分、级数,所以看起来觉得很复杂。

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第11张图片
image

这两个式子有一个共同的特征:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第12张图片
image
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第13张图片
image

如果遍历这些直线,就好比,把毛巾沿着角卷起来:

image

此处受到 荆哲:卷积为什么叫「卷」积? 答案的启发。

只看数学符号,卷积是抽象的,不好理解的,但是,我们可以通过现实中的意义,来习惯卷积这种运算,正如我们小学的时候,学习加减乘除需要各种苹果、糖果来帮助我们习惯一样。

我们来看看现实中,这样的定义有什么意义。

2.6.2 离散卷积的例子:丢骰子

我有两枚骰子:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第14张图片
image

把这两枚骰子都抛出去:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第15张图片
image

求:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第16张图片
image

这里问题的关键是,两个骰子加起来要等于4,这正是卷积的应用场景。

我们把骰子各个点数出现的概率表示出来:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第17张图片
image

那么,两枚骰子点数加起来为4的情况有:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第18张图片
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第19张图片
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第20张图片
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第21张图片
image

3 连续卷积的例子:做馒头

楼下早点铺子生意太好了,供不应求,就买了一台机器,不断的生产馒头。

假设馒头的生产速度是 f(t) ,那么一天后生产出来的馒头总量为:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第22张图片
image

这就是连续的卷积。

2.6.3 图像处理

有这么一副图像,可以看到,图像上有很多噪点:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第23张图片
image

高频信号,就好像平地耸立的山峰:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第24张图片
image

看起来很显眼。

平滑这座山峰的办法之一就是,把山峰刨掉一些土,填到山峰周围去。用数学的话来说,就是把山峰周围的高度平均一下。

平滑后得到:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第25张图片
image

4.2 计算

卷积可以帮助实现这个平滑算法。

有噪点的原图,可以把它转为一个矩阵:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第26张图片
image

然后用下面这个平均矩阵(说明下,原图的处理实际上用的是正态分布矩阵,这里为了简单,就用了算术平均矩阵)来平滑图像:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第27张图片
image

记得刚才说过的算法,把高频信号与周围的数值平均一下就可以平滑山峰。

比如我要平滑a1,1点,就在矩阵中,取出a1,1点附近的点组成矩阵 f ,和 g 进行卷积计算后,再填回去

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第28张图片
image

要注意一点,为了运用卷积, g 虽然和 f 同维度,但下标有点不一样:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第29张图片
image

要注意一点,为了运用卷积, g 虽然和 f 同维度,但下标有点不一样:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第30张图片
image

我用一个动图来说明下计算过程:

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第31张图片
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第32张图片
image
17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第33张图片
image

此图出处:https://mlnotebook.github.io/post/CNN1/

2.7 卷积的应用(再次看回卷积的应用)

用一个模板和一幅图像进行卷积,对于图像上的一个点,让模板的原点和该点重合,然后模板上的点和图像上对应的点相乘,然后各点的积相加,就得到了该点的卷积值。对图像上的每个点都这样处理。由于大多数模板都是对称的,所以模板不旋转。卷积是一种积分运算,用来求两个曲线重叠区域面积。可以看作加权求和,可以用来消除噪声、特征增强。

如:邻域滤波(卷积)

邻域算子值利用给定像素周围像素的值决定此像素的最终输出。如图左边图像与中间图像卷积等于右边图像。目标图像中绿色的像素由原图像中蓝色标记的像素计算得到。

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第34张图片
image

通用线性邻域滤波是一种常用的邻域算子,输入像素加权得到输出像素:

image

65 x 0.1+98 x 0.1+123 x 0.1+65 x 0.1+96 x 0.2 + 115 x0.1 + 63 x 0.1 + 91 x 0.1 + 107 x 0.1 = 91.9约等于92(不知道我有没有算错,算错告诉小嗷公众号或者QQ什么回一声,谢谢)

这时,你就比较理解上面小嗷为啥加这加那的操作等于91.9

另外一个关于卷积的有意思的解释

看了好多关于卷积的答案,看到这个例子才彻底地理解了这个过程~

关于卷积的一个血腥的讲解

比如说你的老板命令你干活,你却到楼下打台球去了,后来被老板发现,他非常气愤,扇了你一巴掌(注意,这就是输入信号,脉冲),于是你的脸上会渐渐地(贱贱地)鼓起来一个包,你的脸就是一个系统,而鼓起来的包就是你的脸对巴掌的响应,好,这样就和信号系统建立起来意义对应的联系。下面还需要一些假设来保证论证的严谨:假定你的脸是线性时不变系统,也就是说,无论什么时候老板打你一巴掌,打在你脸的同一位置(这似乎要求你的脸足够光滑,如果你说你长了很多青春痘,甚至整个脸皮处处连续处处不可导,那难度太大了,我就无话可说了哈哈),你的脸上总是会在相同的时间间隔内鼓起来一个相同高度的包来,并且假定以鼓起来的包的大小作为系统输出。

好了,那么,下面可以进入核心内容——卷积了!

如果你每天都到地下去打台球,那么老板每天都要扇你一巴掌,不过当老板打你一巴掌后,你5分钟就消肿了,所以时间长了,你甚至就适应这种生活了……如果有一天,老板忍无可忍,以0.5秒的间隔开始不间断的扇你的过程,这样问题就来了,第一次扇你鼓起来的包还没消肿,第二个巴掌就来了,你脸上的包就可能鼓起来两倍高,老板不断扇你,脉冲不断作用在你脸上,效果不断叠加了,这样这些效果就可以求和了,结果就是你脸上的包的高度随时间变化的一个函数了(注意理解);

如果老板再狠一点,频率越来越高,以至于你都辨别不清时间间隔了,那么,求和就变成积分了。可以这样理解,在这个过程中的某一固定的时刻,你的脸上的包的鼓起程度和什么有关呢?和之前每次打你都有关!但是各次的贡献是不一样的,越早打的巴掌,贡献越小,所以这就是说,某一时刻的输出是之前很多次输入乘以各自的衰减系数之后的叠加而形成某一点的输出,然后再把不同时刻的输出点放在一起,形成一个函数,这就是卷积,卷积之后的函数就是你脸上的包的大小随时间变化的函数。本来你的包几分钟就可以消肿,可是如果连续打,几个小时也消不了肿了,这难道不是一种平滑过程么?

反映到剑桥大学的公式上,f(a)就是第a个巴掌,g(x-a)就是第a个巴掌在x时刻的作用程度,乘起来再叠加就ok了,大家说是不是这个道理呢?我想这个例子已经非常形象了,你对卷积有了更加具体深刻的了解了吗?

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第35张图片
image

1. 本人是抱着玩一玩的心态,学习opencv(其实深度学习没有外界说的这么高深,小嗷是白板,而且有工作在身并且于代码无关)

2. 大家可以把我的数学水平想象成初中水平,毕竟小嗷既不是代码靠吃饭又不是靠数学吃饭,毕业N年

3. 写文章主要是为了后人少走点弯路,多交点朋友,一起学习

4. 如果有好的图像识别群拉我进去QQ:631821577

5. 就我一个白板,最后还是成的,你们别怕,慢慢来把

17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列_第36张图片
image

分享可以无数次,转载成自己文章QQ邮箱通知一下,未经授权请勿转载。

  • 邮箱:[email protected]

  • QQ群:736854977

  • 有什么疑问公众号提问,下班或者周六日回答,ths

下期再写API函数部分(高斯方框什么),主要直接写代码,估计就复制粘贴。理解性不强,只会调用API。所以,先写写数学部分。

为啥强调卷积呢?深度学习也好,图像识别也好,卷积是常用的基础(对于图像识别和深度学习)。

再看一次,(网易上有)线性代数公开课第一课:方程组的几何解释。

忘了向量,建议网络上查查向量是什么鬼,再看第一课,谢谢。

推荐文章:

你可能感兴趣的:(17.图像处理之线性滤波(线性运算/卷积) --- OpenCV从零开始到图像(人脸 + 物体)识别系列)