博主QQ:1356438802
QQ群:473383394——UVC&OPENCV473383394
平台:Win7 64bits + Visual Studio 2012 + OpenCV 2.4.10
截止今天我终于把《OpenCV3编程入门-毛星云》这本书看完了,看了将近两个月终于看完了!看的挺累的,有点吃力,很多讲算法原理的地方看的很模糊。但是因为我一直带着一个问题去看:如何识别摄像头视频流中的红外LED灯?每看完一个案例我就会想有没有帮助,能不能用的上,然后做一些笔记,还算有点收获。
后面我会把我做了笔记,加了书签(原书电子档并没有书签)的PDF上传,有需要的可以拿去用。
按照惯例,先上目录,我们先把书本内容弄完,再去做自己的实验。
下面红色文字是我自己的总结!
从结果来看,图像滤波就是把图像模糊或者锐化;
从用途来看,图像滤波是为了减少图像上的噪点或者失真。
6.1.1 平滑处理 154
6.1.2 图像滤波与滤波器 154
方框滤波、均值滤波、高斯滤波、中值滤波、双边滤波
6.1.3 线性滤波器的简介 155
低通滤波器、高通滤波器、带通滤波器、带阻滤波器
6.1.4 滤波和模糊 155
高斯低通——模糊
高斯高通——锐化
6.1.5 邻域算子与线性邻域滤波155
线性领域滤波算子:用不同的权重去结合一个小领域内的像素,得到应有的处理效果。
6.1.6 方框滤波(boxFilter) 156
加权系数,就是那个核,核就像一个3x3的方框一样,在图像中移动,根据方框内的加权值计算中心点像素值。
归一化:就是把要处理的量都缩放到一个范围内,如(0, 1),以便统一处理和直观量化。
6.1.7 均值滤波 157
均值滤波:最简单的滤波操作,输出图像的每一个像素是核窗口内输入图像对应像素的平均值(即所有像素加权系数相等)
6.1.8 高斯滤波 159
用一个模板扫描图像中的每一个像素,用模板确定的领域内像素的加权平均灰度值去替代模板中心像素点的值。
高斯滤波器是一类根据高斯函数的形状来选择加权值的线性平滑滤波器。对于抑制服从正太分布的噪声非常有效
6.1.9 线性滤波相关OpenCV源码剖析 160
6.1.10 OpenCV中GaussianBlur函数源码剖析 164
6.1.11 线性滤波核心API函数 165
6.1.12 图像线性滤波综合示例170
可以仔细看看案例,体会下这几个滤波方法的结果有什么区别,我觉得区别最大的是高斯滤波。
6.2.1 非线性滤波概述 175
6.2.2 中值滤波 175
中值滤波:用像素点领域灰度值的中位值来代替该像素点的灰度值。对于斑点噪声和椒盐噪声很有效。
缺点:中值滤波花费的时间是均值滤波的5倍以上。
6.2.3 双边滤波 177
双边滤波:结合图像的空间领近度(定义域)和像素值相似度(值域)的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的。
6.2.4 非线性滤波相关核心API函数 178
对于中值滤波,主要是孔径(核)大小的设置
对于双边滤波,其实就是指定 定义域核的大小和值域核的大小。
6.2.5 OpenCV中的5种图像滤波综合示例 181
作者的原话:通过滑动滚动条,就可以控制图像在各种平滑处理下的模糊度,有一定的可玩性。
6.3.1 形态学概述 187
数学形态学包括,二值腐蚀和膨胀、二值开关运算、骨架抽取、极限腐蚀、击中击不中变换、形态学梯度、Top-hat变换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开关运算、灰值形态学梯度等。
膨胀和腐蚀的功能:
腐蚀和膨胀是对白色部分而言的,膨胀是对图像中的高亮部分进行扩张,腐蚀是原图中高亮部分缩小面积。
6.3.2 膨胀 188
膨胀就是求局部最大值的操作。
6.3.3 腐蚀 189
腐蚀就是求局部最小值的操作。
6.3.4 相关OpenCV源码分析溯源 190
erode和dilate函数内部都调用了morphOp
6.3.5 相关核心API函数讲解 191
关键是用getStructuringElement()函数生成膨胀核、腐蚀核,有三种核:矩形核(MORPH_RECT)、十字形核(MORPH_CROSS)、椭圆形核(MORPH_ELLIPSE)。
6.3.6 综合示例:腐蚀与膨胀195
有一定的可玩性!
6.4.1 开运算 199
开运算,先腐蚀后膨胀。用来消除小物体,在纤细点处分离物体,并且在平滑较大物体的边界的同时不明显改变其面积。
dst = open(src, element) = dilate(erode(src, element))
6.4.2 闭运算 200
闭运算,先膨胀后腐蚀。排除小型黑色区域。
dst = close(src, element) = erode(dilate(src, element))
6.4.3 形态学梯度 200
膨胀图与腐蚀图之差。用来保留物体的边缘轮廓。
dst = dilate(src, element) - erode(src, element)
6.4.4 顶帽 201
dst = tophat(src, element) = src - open(src, element)
顶帽运算可以用来分离比邻近点 亮一些的斑块,分离即剔除。因为前景物体会比较亮,用顶帽运算将其剔除,剩下就是背景!
6.4.5 黑帽 202
dst = blackhat(src, element) = close(src, element) - src
黑帽运算可以用来分离比邻近点 暗一些的斑块,分离即剔除。因为背景物体会比较暗,用黑帽运算可以把背景的细节掩盖,从而留下的是前景物体的轮廓。
6.4.6 形态学滤波OpenCV源码分析溯源 203
关键的morphologyEx()函数
6.4.7 核心API函数:morphologyEx() 205
标识符:
6.4.8 各形态学操作使用范例一览206
6.4.9 综合示例:形态学滤波208
通过这里的例程,可以详细感受下各种形态学操作的效果
6.5.1 漫水填充的定义 214
漫水填充:用特定的颜色填充连通区域,通过设置可连通像素的上下限以及连通方式来达到不同的填充效果。
结果就是,让某一块颜色接近的区域全部上一个色。
6.5.2 漫水填充法的基本思想214
当邻近像素点位于给定的范围内或在原始seedPoint像素值范围内时,FloodFill函数就会为这个点涂上颜色。
6.5.3 实现漫水填充算法:floodFill函数 214
int floodFill(InputOutputArray image, Point seedPoint, Scalar newVal, Recv *recv=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4)
seedPoint,起始点/种子像素
newVal,要填充的色值
loDiff,upDiff,可连通像素的上下限
flags,FLOODFILL_FIXED_RANGE,FLOODFILL_MASK_ONLY,
fixed——固定的
6.5.4 综合示例:漫水填充 216
固定范围:考虑当前像素和种子像素之间的差
浮动范围:考虑当前像素和相邻像素之间的差
6.6.1 引言 223
图像金字塔,就是图像经过缩放后生成的N张图片组成的金字塔。
缩放图片有两种方法:
6.6.2 关于图像金字塔 223
向上是图像尺寸加倍,向下是图像尺寸减半,和金字塔的方向相反!
pryDown()是一个会丢失信息的函数。为了恢复原来更高分辨率的图像,我们要获得由降采样操作丢失的信息,这就与拉普拉斯金字塔有关!
6.6.3 高斯金字塔 225
6.6.4 拉普拉斯金字塔 226
可是一般情况下,你拿到一张图片时不可能有它的拉普拉斯金字塔残差,所以向上采样放大后的图像必然是模糊的!有什么卵用?!
6.6.5 尺寸调整:resize()函数 227
缩放比例,由dsize(目标尺寸)或者fx(水平缩放系数) / fy(垂直缩放系数),决定。
缩小图像一般用CV_INTER_AREA,放大图像一般用CV_INTER_LINEAR。
6.6.6 图像金字塔相关API函数 230
6.6.7 综合示例:图像金字塔与图片尺寸缩放 234
利用物体与背景之间的灰度差异,将物体像素点的灰度值设定为0(黑色),其他的像素点的灰度值设置为255(白色),这时很方便观察物体。
这个功能非常好,正好用于手写笔的识别!阈值化之后,手写笔的光点将非常突出,直接求其坐标即可!
6.7.1 固定阈值操作:Threshold()函数 238
典型应用:对灰度图像进行阈值操作得到二值图像。
THRESH_BINARY: 二值阈值化
THRESH_BINARY_INV: 反向二值阈值化
THRESH_TRUNC: 截断阈值化
THRESH_TOZERO: 超过阈值被置为0
THRESH_TOZERO_INV: 低于阈值被置为0
6.7.2 自适应阈值操作:adaptiveThreshold()函数 239
6.7.3 示例程序:基本阈值操作240
可以看下五种阈值化方法的效果!
7.1.1 边缘检测的一般步骤 248
滤波、增强、检测
7.1.2 canny算子 248
当今最优的边缘检测算法!输入图像必须是单通道8位图像,即灰度图。
Canny边缘检测步骤:
7.1.3 sobel算子 253
sobel结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。
7.1.4 Laplacian 算子256
Laplacian算子是N维欧几里得空间中的一个二阶微分算子,定义为梯度grad的散度div。二阶导数可以用来进行检测边缘。另外Laplacian使用了图像梯度,它内部的代码其实是调用了Sobel算子。
7.1.5 scharr滤波器 259
7.1.6 综合示例:边缘检测 262
7.2.1 霍夫变换概述 267
霍夫变换是图像处理中从图像中识别几何形状的基本方法之一。
经典霍夫变换用来检测图像中的直线,后来霍夫变换扩展到任意形状物体的识别。
7.2.2 OpenCV中的霍夫线变换268
霍夫变换的直接输入只能是边缘二值图像!
OpenCV支持三种:标准霍夫变换、多尺度霍夫变换、累计概率霍夫变换
7.2.3 霍夫线变换的原理 268
通过(x, y)点的直线族的极坐标系表达式:r = x cosQ + y sinQ
每个表达式在极径极角平面可以得到一条正弦曲线,如果三条曲线相交,说明它们通过了同一条直线,即三个表达式对应的那三个点经过同一条直线。
7.2.4 标准霍夫变换:HoughLines()函数 270
输入的必须是二值图像,最终输出是线条矢量,极坐标表示。
7.2.5 累计概率霍夫变换:HoughLinesP()函数 272
输入的必须是二值图像,最终输出是线条矢量,用起始点、结束点两个坐标表示。
7.2.6 霍夫圆变换 274
可以用来检测跟踪圆形物体
7.2.7 霍夫梯度法的原理 275
核心思想:取样一个圆心点,计算累加器中的点与圆心之间的距离,如果距离相等的点足够多,那么认为这个圆存在!
7.2.8 霍夫梯度法的缺点 276
7.2.9 霍夫圆变换:HoughCircles()函数 276
输入灰度图像,输出圆矢量,用圆心坐标和半径表示。
7.2.10 综合示例:霍夫变换278
7.3.1 重映射的概念 281
直观的效果就是,可以对图像进行,中心对称、轴对称、缩小放大等处理。
7.3.2 实现重映射:remap()函数 282
需要传入x和y两组映射关系
7.3.3 基础示例程序:基本重映射283
7.3.4 综合示例程序:实现多种重映射 285
7.4.1 认识仿射变换 289
仿射变换比重映射的效果更复杂些:可以将图像缩小放大、扭曲、旋转再平移。
7.4.2 仿射变换的求法 290
7.4.3 进行仿射变换:warpAffine()函数 291
输入2x3的变换矩阵
7.4.4 计算二维旋转变换矩阵:getRotationMatrix2D()函数 292
给旋转中心、旋转角度、缩放系数,计算旋转矩阵
7.4.5 示例程序:仿射变换 292
另外一个求仿射变换矩阵的函数:getAffineTransform(srcTriangle, dstTriangle)
输入两组三点坐标,得出变换矩阵
7.5.1 直方图均衡化的概念和特点296
直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法。
7.5.2 实现直方图均衡化:equalizeHist()函数 297
就是把直方图的每个灰度等级进行归一化处理,求每种灰度的累计分布,得到一个映射的灰度映射表。
7.5.3 示例程序:直方图均衡化298
效果就是,图片会更明亮些!
8.1.1 寻找轮廓:findContours()函数 304
输入为二值图像
每个轮廓存储为点向量,输出就是点向量集——点向量的向量
8.1.2 绘制轮廓:drawContours()函数 305
指定要绘制的点向量集,点向量序号(轮廓序号),轮廓颜色,轮廓线宽
8.1.3 基础示例程序:轮廓查找306
这个案例里面有个语法很屌:
srcImage = srcImage > 119; //srcImage取大于阈值119的那部分
8.1.4 综合示例程序:查找并绘制轮廓 308
8.2.1 凸包 312
给定二维平面的点集,凸包就是将最外层的点连接起来构成的凸多边形。
8.2.2 寻找凸包:convexHull()函数 313
void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true)
输入参数points,二维点集,用Mat / std::vector
输出参数hull,按照后面两个案例代码:既可以保存凸包所有点在points中的下标序号,也可以直接保存凸包点坐标
8.2.3 基础示例程序:凸包检测基础313
vector
8.2.4 综合示例程序:寻找和绘制物体的凸包 315
vector
8.3.1 返回外部矩形边界:boundingRect()函数 318
最外面的矩形,不一定是最小的那个矩形
8.3.2 寻找最小包围矩形:minAreaRect()函数 318
最小矩形,可以全部包围!
8.3.3 寻找最小包围圆形:minEnclosingCircle()函数 318
面积最小的包围圆形。
分水岭的概念和形成可以通过模拟浸入过程来说明:
在每一个局部极小值表面,刺穿一个小孔,然后把整个模型慢慢浸入水中,随着浸入的加深,每一个局部极小值的影响域慢慢向外扩展,在两个集水盆汇合处构筑大坝,即形成了分水岭。
能理解概念,但是搞不懂,它有什么卵用?
8.5.1 实现分水岭算法:watershed()函数 334
8.5.2 综合示例程序:分水岭算法 334
8.6.1 实现图像修补:inpaint()函数 340
这个功能有些实际意义,其实就是利用破坏区域的边缘的颜色和结构,繁殖和混合到损坏区域。所以如果损坏区域太大,修补效果也就差强人意了!
8.6.2 综合示例程序:图像修补341
案例中有鼠标回调函数的使用,实现了鼠标画线功能。
9.2.1 计算直方图:calcHist()函数 347
用于计算一个或者多个阵列的直方图。注意这个函数可以输入多个图像或者数组集。但是你看不懂它怎么用?
9.2.2 找寻最值:minMaxLoc()函数 348
9.2.3 示例程序:绘制H—S直方图 348
看了这个案例就知道calcHist()函数怎么用了!而且这里是求二维直方图
程序中出现的MatND类是用于存储直方图的一种数据结构。
9.2.4 示例程序:计算并绘制图像一维直方图 350
可以再看看求一维直方图calcHist()的用法
9.2.5 示例程序:绘制RGB三色直方图 352
三色直方图,都是一维直方图
9.3.1 对比直方图:compareHist()函数 355
double compareHist(InputArray H1, InputArray H2, int method)
比较两个大小相同的直方图,method有4种比较方法。
9.3.2 示例程序:直方图对比356
4种方法,Correlation和Intersection的返回值越大相似度越高。
9.4.1 引言 360
直方图可以看做一个概率函数,如果将测试纹理图和原始纹理图进行比较,概率越相近,则说明其纹理越相似。
反向投影就是首先计算某一特征的直方图模型,然后使用这个模型去寻找测试图像中存在的该特征的方法。
9.4.2 反向投影的工作原理 360
由已知图像得到一个直方图模型,然后对测试图像的每一个像素点,求其色调,然后找到该色调在直方图模型中的bin位置,再查询该bin的数值,最后归一化。
这样得出的一幅图像,实际上就是直方图模型在测试图像的一个映射。
9.4.3 反向投影的作用 361
在输入图像中查找与模板图像最匹配的区域,也就是定位模板图像出现在输入图像中的位置。
9.4.4 反向投影的结果 361
9.4.5 计算反向投影:calcBackProject()函数 361
9.4.6 通道复制:mixChannels()函数 362
9.4.7 综合程序:反向投影 363
在这里,测试图像是源图像,也就是把直方图模型映射到原图!
两个图例的分析:
1. 比如一维的灰度直方图来讲:如果bin的数量越少,那么单个bin所覆盖的灰度值范围就更宽,进行映射时,颜色相近的像素会被取相同的bin值,这时反向投影出来的图像就会损失细节,而只有轮廓,如右图。这个有点类似于调整滤波参数。
2. 在这个右图中,bin数量更多,反向投影结果的图像就有更多的细节。
9.5.1 模板匹配的概念与原理367
模板匹配不是基于直方图的,而是通过在输入图像上滑动图像块,对实际的图像块和输入图像进行匹配的一种匹配方法。
这样的方法容错率太低了吧,如果测试图片中的人脸是歪的,或者是侧脸呢?!
9.5.2 实现模板匹配:matchTemplate()函数 367
void matchTemplate(InputArray image, InputArray templ, OutputArray result, int method)
从image中搜索模板templ,templ的尺寸一般比image小很多。
method有6中匹配方法:
随着从简单的测量(平方差)到更复杂的测量(相关系数),我们可以获得越来越准确的匹配。
9.5.3 综合示例:模板匹配 369