目录
6.7.2、自定义阈值操作:adaptiveThreshold()
第六章、图像处理
imgproc组件:image 和 process的缩写,即图像处理模块,包括:线性和非线性的图像滤波、图像的几何变换、其他图像变换、直方图相关、结构分析和形状描述、运动分析和对象跟踪、特征检测、目标检测。
-
6.1、线性滤波:方框滤波、均值滤波、高斯滤波
-
6.1.1、平滑处理
- 平滑处理也称模糊处理,用来减少图像上的噪点或失真,涉及到降低图像分辨率时,也可以使用平滑处理
-
6.1.2、图像滤波与滤波器
- 图像滤波,指在尽量保留图像细节特征的条件下对目标图像的噪声进行抑制。消除图像中的噪声成分叫做图像的平滑化或滤波操作。信号或图像的能力大部分集中在幅度谱的低频和中频段,在较高频段,有用的信息经常被噪声掩膜,因此一个能减低高频成分幅度的滤波器就能够减弱噪声的影响。图像滤波的目的有两个:1、抽出对象的特征作为图像识别的特征模式;2、为适应图像处理的要求,消除图像数字化时所混入的噪声。滤波处理的两个要求:1、不能损坏图像的轮廓及边缘等重要信息,2、使图像清晰视觉效果好。
- 平滑滤波是低频增强的空间域滤波技术。目的:模糊和消除噪音。空间域的平滑滤波一般采用简单平均法进行,就是求邻近像元点的平均亮度值。邻域的大小与平滑的效果直接相关,邻域越大平滑的效果越好,但邻域过大,平滑也会使边缘信息损失的越大,从而使输出的图像变得模糊,因此要合理选择邻域大小。
- 可以把滤波器想象成一个包含加权系数的窗口,档使用这个滤波器平滑处理图像时,就把这个窗口放到图像上,透过这个窗口来看我们得到的图像。
- 方框滤波-----BoxBlur函数;均值滤波(邻域平均滤波)-----Blur函数; 高斯滤波-----GaussianBlur函数; 中值滤波-----medianBlur函数; 双边滤波-----bilateralFilter函数。
-
6.1.3、线性滤波器的简介
- 线性滤波器经常用于剔除输入信号中不想要的频率或者从许多频率中选择一个想要的频率
- 低(高)通滤波器:允许低(高)频率通过
- 带通滤波器:允许一定范围频率通过
- 带阻滤波器:阻止一定范围频率通过并且允许其他频率通过
- 全通滤波器:允许所有频率通过,仅仅改变相位关系
- 陷波滤波器:阻止一个狭窄频率范围通过,是一种特殊的带阻滤波器
-
6.1.4、滤波和模糊
- 滤波是将信号中特定波段频率滤除的操作,是抑制和防止干扰的一项重要措施。
- 低通模糊,高通锐化。
-
6.1.5、邻域算子与线性邻域滤波
- 邻域算子(局部算子)是利用给定像素周围的像素值的决定此像素的最终像素值的一种算子。线性邻域滤波是一种常用的邻域算子,像素的输出值取决于输入像素的加权和。
- 邻域算子除了用于局部色调调整以外,还可以用于图像滤波,以实现图像的平滑和锐化,图像边缘增强或者图像噪声的去除。线性滤波算子用不同的权重去结合一个小邻域内的像素,来得到应有的处理效果。
-
6.1.6、方框滤波
void boxFilter (InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1),boolnormalize=true, int borderType = BORDER_DEFAULT)
- 第一个参数:输入图像,该函数对通道是独立处理的,且可以处理任意通道数的图片。
- 第二个参数:目标图像
- 第三个参数:输出图像的深度,-1表示使用原图深度
- 第四个参数:内核的大小,Size(w,h)。
- 第五个参数:锚点(被平滑的那个点)。有默认值(-1,-1),点坐标是负值表示取核的中心为锚点。
- 第六个参数:默认值为true,表示内核是否被其他区域归一化了
- 第七个参数:用于推断图像外部像素的某种边界模式,一般不去管
-
6.1.7、均值滤波
- 用一片图像区域的各个像素的均值来代替原图像中的各个像素值。在图像上对目标像素给出一个内核,包括了周围的临近像素,用内核中的全体像素的平均像素值来代替原来像素值。
- 不能很好的保护图像细节,在图像去噪的同时也破坏了图像的细节 部分,使图像变得模糊,不能很好的去除噪声
- blur函数:对输入突出进程均值滤波后输出
void blur(InputArray src, OutputArray dst, Size ksize, Point anchor = Point(-1,-1), int dorderType=BORDER_DEFAULT)
- 第一个参数:输入图像
- 第二个参数:输出图像
- 第三个参数:内核的大小,
- 第四个参数:锚点(被平滑的那个点)
- 第五个参数:一般不管
-
6.1.8、高斯滤波
- 高斯滤波就是对整幅图像进行加权平均和过程,每一个像素点的值都由其本身和邻域内的其他像素值经过加权平均后得到。高斯滤波可以消除高斯噪声,广泛应用于图像处理的减噪过程。具体操作是:用一个模板(卷积、掩膜)扫描图像中的每一个像素,用模板确定的邻域内像素的加权平均灰度值取替代模板中心像素点的值。
- 高斯滤波器是根据高斯函数的形状来选择权值的线性平滑滤波器。高斯平滑滤波器对于抑制服从正态分布的噪声非常有效。
void GaussianBlur(InputArray src, OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT)
- 第一个参数:输入图像
- 第二个参数:输出图
- 第三个参数:高斯内核大小
- 第四个参数:表示高斯核函数在x方向的标准偏差
- 第五个参数:表示高斯核函数在y方向的标准偏差。若sigmaY为0,将它设为sigmaX,如果sigmaX、Y都是0,就由ksize.width /height计算出来
- 第六个参数:用于推断图像外部像素的某种边界模式,一般不管
-
6.1.9、线性滤波相关OpenCV源码剖析
- OpenCV boxFilter 函数源码解析
- 其中,ptr是用来动态分配的对象的智能指针模板类。先复制源图像的形参mat数据到临时变量,定义一些临时变量,再处理ddepth小于0的情况,接着处理borderType的情况,最后调用FilterEngine滤波引擎创建一个BoxFilter
- FilterEngine类解析:opencv图像滤波核心引擎
- FilterEngine类是图像滤波的核心,各种滤波函数blur、GaussianBlur,其实就是在函数末尾处定义了一个Ptr<FilterEngine>类型的f,然后f->apply(src,dst)了一下。这个类可以把所有的滤波操作加到图像上,包含了所有必要的中间缓存器。有很多和滤波相关的create函数的返回值都是直接Ptr<FilterEngine>,比如:···cv::createSeparableLinearFilter();···cv::createLinearFilter();
- 函数原型:Ptr<FilterEngine>createLinearFilter(int srcType, int dstType, InputArray kernel, Pointanchar=Point(-1,-1), double delta=0, int rowBorderType=BORDERDEFAULT, intcolumnBorderType=-1, const Scalar&borderValue =Scalar()):使用FilterEngine类可以分块处理大量图像,构造复杂的管线,其中就包含一些进行滤波阶段。
- OpenCV boxFilter 函数源码解析
-
6.1.10、GaussianBlur函数源码
-
6.1.11、线性滤波核心API函数
- 1、方框滤波:boxFilter函数。:
void boxFilter(InputArray src, OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1),boolnormalize=true, int boederType=BORDER_DEFAULT)
:- 第一个参数:输入图像
- 第二个参数:输出图像
- 第三个参数:输出图像的深度,-1表示使用原图深度
- 第四个参数:内核大小
- 第五个参数:锚点
- 第六个参数:默认值为true,表示内核是否被其区域归一化
- 第七个参数:一般不管
- 2、均值滤波:blur函数
void bl ur(I nputArray src , OutputArraydst , Size ksize , Poi nt anchor=Point(-l , - l) , i nt borderType=BORDER_DEFAULT )_
- 第一个参数:输入图像
- 第二个参数:输出图像
- 第三个参数:内核
- 第四个参数:锚点
- 第五个参数:不去管
- 3、高斯滤波:GaussianBlur
C++ : void GaussianBlur(InputArray src , OutputArray dst, Size ksize , double sigmaX, double sigmaY=O, intborderType=BORDER DEFAULT )
- 第一个参数:输入图像
- 第二个参数:输出图像
- 第三个参数:内核.
- 第四个参数:表示高斯核函数在x方向的标准偏差
- 第五个参数:表示高斯核函数在y方向的标准偏差。若sigmaY为0,将它设为sigmaX,如果sigmaX、Y都是0,就由ksize.width /height计算出来
- 第六个参数:用于推断图像外部像素的某种边界模式,一般不管
- 1、方框滤波:boxFilter函数。:
-
6.1.12、综合示例
-
-
6.2、非线性滤波:中值滤波、双边滤波
-
6.2.1、线性滤波概述
- 线性滤波器:两个信号之和的响应和它们各自响应之和相等,也就是每个像素的输出值是一些输入像素的加权和,线性滤波器易于构造,并且易于从频率响应角度进行分析。然而在大多数情况下,使用邻域像素的非线性滤波回得到更好的效果,比如在噪声是散粒噪声而不是高斯噪声,即图像偶尔会出现很大的值的时候,用高斯滤波器对图像进行模糊的话,噪声像素是不会被去除的,它们只是被转换为更为柔和但仍然可见的散粒,也就是需要中值滤波
-
6.2.2、中值滤波
- 中值滤波是一种典型的非线性滤波技术,是用像素点邻域灰度值的中值来代替该像素点的灰度值,该方法在去除脉冲噪声、椒盐噪声的同时又能保留图像的边缘细节。中值滤波是基于排序统计理论的一种能有效抑制噪声的非线性信号处理技术,其基本原理是把数字图像或数字序列中一点的值用该点的 个邻域中各点值的中值代替,让周围的像素值接近真实值,从而消除孤立的噪声点。
- 优点:在均值滤波器中,噪声成分被放入平均计算中,输出会受到噪声影响。在中值滤波器中,噪声成分很难选上,几乎不会影响输出,中值滤波在消除噪声和保存边缘方面都是一个很好的方法
- 缺点:耗费时间
- 按强度值大小排列像素点;选择排序像素集中点作为新值
- 一般采用奇数点的邻域来计算中值,但像素点是偶数时,中值就取排序像素中间两点的平均值
- 对一些细节多的图像不太合适
-
6.2.3、双边滤波
- 双边滤波是结合图像的空间邻近度和像素相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部的特点。
- 好处是可以做边缘保存。双边滤波器顾名思义,比高斯滤波多了个高斯方差 sigma-d 它是基于空间分布的高斯滤波函数,所以在边缘附近 离得较远的像素不会对边缘上像素值影响太多,这样就保证了边缘附近像素值的保存 但是,由于保存了过多的高频信息,对于彩色图像里的高频噪声,双边滤波器不能够干净地滤掉能对于低频信息进行较好地滤波
-
6.2.4、非线性滤波相关核心API函数
- 1、中值滤波:medianBlur
void medianBlur(InputArray src, OutputArray dst,int ksize)
:输入图像、输出图像、核大小
- 2、双边滤波:bilateralFiter
void bilateralFilter(InputArray src, OutputArray dst, int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)
- 输入图像
- 输出图像
- 滤波过程中,每个像素邻域的直径
- 颜色空间滤波器的sigma值,值越大,该像素邻域内有越宽广的颜色会被混合到一起,产生较大的半相等颜色区域
- 坐标空间中滤波器的sigma值,坐标空间的标注方差。值越大月圆的像素会相互影响,从而使更大的区域中足有的相似的颜色获取相同的颜色。
- 用于推断图像外部像素的某种边界模式
- 1、中值滤波:medianBlur
-
6.2.5、综合示例
-
-
6.3、形态学滤波(1):腐蚀与膨胀
-
6.3.1、形态学概述
- 数学形态学是一门专门在格论和拓扑学基础上的图像分析学科,包括二值腐蚀和膨胀、二值开闭运算、骨架抽取、极限腐蚀、击中击不中交换、形态学梯度、top-hat交换、颗粒分析、流域变换、灰值腐蚀和膨胀、灰值开闭运算、灰值形态学梯度
- 腐蚀和膨胀的功能:消除噪声、分割出独立的图像元素,在图像中连接相邻的元素、寻找图像中的明显的极大值区域或极小值区域、求出图像的梯度
- 腐蚀和膨胀是针对白色部分(高亮部分),效果图比原图更大(小)的高亮区域
-
6.3.2、膨胀
- 求局部最大值的操作。腐蚀和膨胀就是将图像与核进行卷积。核可以是任何形状核大小,拥有一个单独定义的参考点,即锚点。多数情况下,核是一个小的,中间带有参考点和实心正方形或者圆盘,核即模板或掩码。
- 膨胀是求局部最大值的操作,核与图像进行卷积,计算核覆盖的区域的像素点的最大值,并把这个最大值赋值给参考点指定的像素。会使图像中的高亮区域逐渐增长。
-
6.3.3、腐蚀
- 与膨胀相反的操作,即求局部最小值
-
6.3.5、相关函数
- 1、膨胀:dilate函数
void dilate(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue())
- 1:输入图像;2:输出突起
- 3:核,为NULL时,表示使用参考点位于中心3x3的核。一般使用函数getStructuringElement配合使用,这个函数会返回指定形状核尺寸的结构元素(内核矩阵),第一个参数表示内核的形状:矩形MORPHRECT;交叉型:MORPHCROSS;椭圆形:MORPHELLIPSE。而第二个第三个参数分别时内核的尺寸核锚点的位置。在调用erode已经dilate函数之前,先定义一个Mat类型的变量来获得getStructuringElement函数的返回值,锚点的位置一般是Point(-1,-1),表示位于中心。只有十字形的元素形状唯一依赖锚点的位置,其他情况,锚点只是影响了形态学运算结果的偏移。
- 4:锚点的位置
- 5:迭代使用erode()的次数,默认值1
- 6:用于推断图像外部像素的某种边界模式
- 7:一般不管
- 使用erode函数一般只需填前三个参数,后边的参数有默认值。
- 2、腐蚀:erode函数
void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),int iterations=1, int borderType=BORDER_CONSTANT, const Scalar& borderValue=morphologyDefaultBorderValue())
- 参数如上dilate函数参数作用
- 1、膨胀:dilate函数
-
6.3.6、腐蚀核膨胀实例
-
-
6.4、形态学2:开运算、闭运算、形态学梯度、顶帽、黑帽
-
6.4.1、开(闭)运算
- 开运算就是先腐蚀后膨胀的过程。 开运算可以用来消除小物体,在纤细点分离物体,并且在平滑较大的物体的边界的同时不明显改变其面积。
dst = open(src,element)= dilate(erote(src,element))
- 闭运算是先膨胀后腐蚀,能够消除小型黑洞(黑色区域)
dst = clese(src,element)= erote(dilate(src,element))
- 开运算就是先腐蚀后膨胀的过程。 开运算可以用来消除小物体,在纤细点分离物体,并且在平滑较大的物体的边界的同时不明显改变其面积。
-
6.4.3、形态学梯度
- 是膨胀图与腐蚀图之差:
dst= morth-grad(src,element)=dilate(src,element)-erote(src,element)
- 对二值图像进行这一操作可以将团块(blob)的边缘突出。可以用形态学梯度来保留物体的边缘轮廓。
- 是膨胀图与腐蚀图之差:
-
6.4.4、顶帽
- 原图像与开运算的结果图之差。
dst=tophat(src,element)=src-open(src,element)
。开运算带来的结果是放大了裂缝或者局部低亮度的区域。从原图减去开运算后的图,得到的效果图突出了比原图轮廓周围的区域更明亮的区域且这一操作与选择的核的大小相关。 - 顶帽运算往往用来分离比临近点亮一些的斑块。在一副图像具有大幅的背景而微小物品比较有规律的情况下,可以用顶帽运算进行背景提取。
- 原图像与开运算的结果图之差。
-
6.4.5、黑帽
- 是闭运算效果图与原图之差。
dst = blackhat(src,element)=close(src,element)-src
- 黑帽突出了比原图轮廓周围的区域更暗的区域,用来分离比临近点暗一些的斑块。
- 是闭运算效果图与原图之差。
-
6.4.7、核心函数:morphologyEx()
void morphologyEx(IputArray src, OutputArray dst, int op, InputArraykernel, Pointanchor=Point(-1,-1), int iterations=1,int borderType = BORDER_CONSTANT,const Scalar& borderValue= morphologyDefaultBorderValue())
- 1:输入图像;2:输出图像;
- 3:形态学运算的类型。
- 4:运算的核。同腐蚀膨胀操作中的参数
- 5:锚点位置
- 5:迭代使用函数的次数;7:推断外部函数的某种边界模式;8:一般不管
-
6.4.8、形态学操作使用范例
-
6.4.9、综合示例:形态学滤波
-
-
6.5、漫水填充
-
6.5.1、漫水填充的基本思想
- 自动选中了和种子点相连的区域,接着该区域替换成指定的颜色,经常用来标记或者分离图像的一部分进行处理或分析,也可也用来从输入图像获取掩码区域,掩码会加速处理过程,或者只处理掩码指定的像素点。漫水填充是查找和种子点连通的颜色相同的点,c+有两个函数版本,一个不带掩膜一个带掩膜。掩膜mask就是用于进一步控制哪些区域将被填充颜色。两个版本的FloorFill都必须在图像中选择一个种子点,然后吧临近区域所有相似点填充上同样的颜色,不同的是,不一定将所有的临近像素点都染上同一颜色,漫水填充操作的结果总是在某个连续的区域、当临近像素点位于给定的范围内或在原始像素值范围内时,就会给这个点涂色。
-
6.5.3、实现漫水填充算法:floodFill
int floodFill(InputArray image, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff = Scalar(), int flags=4)
int floodFill(InputArray image,InputOutArray mask, Point seedPoint, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff = Scalar(), int flags=4)
- 1:输入图像
- 2:这是第二个版本独享的参数,表示操作掩膜。漫水填充不会填充掩膜mask的非零像素区域。一个边缘检测算子的输出可以用来作为掩膜以防止填充到边缘。也可以在多次的函数调用中使用同一个掩膜,保证填充的区域不会重叠。掩膜mask会比需要填充的图像大。所以mask中与输入图像(x,y)像素点相对应的点的坐标为(x+1,y+1)
- 3:漫水填充的起始点
- 4:像素点被染色的值,即在重绘区域像素的新值
- 5:可选参数,用于设置函数将要重绘区域的最小边界矩形区域
- 6:当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之负差的最大值。
- 7:当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之正差的最大值。
- 8:标识符。
-
6.5.4、综合示例:漫水填充
-
6.6、图像金字塔与图片尺寸缩放
-
6.6.1、引言
- 要对图像进行放大或缩小尺寸,OpenCV提供如下两种方法
- resize函数,这是最直接的方式
- pyrUp()、pyrDown()函数,即图像金字塔相关的两个函数,对图像进行向上采样和向下采样的操作。
- pyrUp()、pyrDown()在imgproc模块的Image Filtering子模块里。resize在imgproc模块的Geometric Image Transformations子模块
- 要对图像进行放大或缩小尺寸,OpenCV提供如下两种方法
-
6.6.2、关于图像金字塔
- 金字塔底部是待处理图像的高分辨率,顶部是低分辨率的近似。
- 高斯金字塔:用来向下采样,主要的图像金字塔
- 拉普拉斯金字塔:用来从金字塔低层图像重建上层未采样图像,可以预测残差也可以对图像进行最大程度的还原,配合高斯金字塔一起使用
- 两者的区别在于:高斯金字塔用来向下采样图像,拉普拉斯用来从底层图像向上采样重建一个图像。
- 要从金字塔第 i 层生成第 i+1 层,先要对 i 层进行卷积,然后删除所有偶数行和偶数列,新得到的图像面积会变成原图像的四分之一,按此过程就可以产生出整个金字塔。当图像向金字塔的上层移动时,尺寸和分辨率就会减低。
- 金字塔底部是待处理图像的高分辨率,顶部是低分辨率的近似。
-
6.6.3、高斯金字塔
- 高斯金字塔时通过高斯平滑和亚采样获得一系列下采样图像。高斯金字塔包含了一系列低通滤波器,其截止频率从上一层到下一层以因子2逐渐增加,所以高斯金字塔可以跨越很大的频率范围。
- 对图像的下采样
- 对图像进行高斯内核卷积;将所有偶数行和列去除
- 得到的图像即为+1,结果图像只有原图像的四分之一。
- 对图像的上采样
- 将图像在每个方向扩大为原来的两倍,新增的行和列以0来填充
- 使用先前同样的内核(乘以4)与放大后的图像卷积,获得新增图像的近似值
- 获得的图像就是放大后的图像,但是与原图相比会比较模糊。
- 要想减少在放大缩小过程中的损失,形成了拉普拉斯金字塔
-
6.6.4、拉普拉斯金字塔
- 第i层的数学定义: = - UP() 。UP()操作是将原图像中位置为(x,y)的像素映射到目标图像的(2x+1, 2y+1)位置,即在进行向上采样。符号表示卷积。表示5x5的高斯内核。
- 拉普拉斯金字塔式通过原图像减去先缩小后再放大的图像的一系列图像组成。
- 图像金字塔的一个重要应用是图像分割,先建立一个图像金字塔,然后对和的像素直接依照对应的关系,建立起父与子的关系,而快速初始分割可以现在金字塔高层的低分辨率图像上完成,然后逐层对分割加以优化。
-
6.6.5、尺寸调整:resize()函数
- 如果原图像设置了ROI,那么resize函数对ROI区域进行调整图像尺寸的操作,来输出到目标图像中,若目标图像设置了ROI区域,会将原图像进行尺寸调整并填充到目标图像的ROI中。很多时候并不用考虑第二个参数dst的初始图像尺寸和类型。
-
void resize(InputArray src, OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation = INTER_LINEAR)
- 1:输入图像;2:输出图像;
- 3:输出图像大小,若为0,则dsize = Size(round(fx*src.cols),round(fy*src.rows))
- 4:沿水平缩放的缩放系数。有默认值0,当等于0时,由下式进行计算(double)dsize.width/src.cols
- 5:沿垂直缩放的缩放系数。有默认值0,当等于0时,由下式进行计算(double)dsize.height/src.rows
- 6:指定插值方式。INTER_NEAREST-----最近邻插值;INTER_LINEAR-----线性插值(默认);INTER_AREA-----区域插值(利用像素区域关系的重采样插值);INTER_CUBIC-----三次样条插值(超过4x4像素邻域内的双三次插值);INTER_LANCZOS4-----Lanczos插值(超过8x像素邻域的)
-
- 缩小图像使用区域插值,方法图像一般用三次样条插值(效率不高、慢、不推荐)或Lanczos(效率高速度快推荐)
-
//调用范例1 Mat dstImage = Mat::zeros(512,512,CV_8UC3);//新建一张512x512尺寸的照片 Mat srcImage = imread("1.jpg"); //显式指定dsize=dstImage.size(),那么fx和fy会被计算出来,不用额外指定 resize(srcImage, dstImage, dstImage.size()); //调用范例2 Mat dstImage; Mat srcImage = imread("1.jpg"); //指定fx和fy,让函数计算出目标图像的大小 resize(srcImage, dstImage,Size(),0.5,0.5)
- 如果原图像设置了ROI,那么resize函数对ROI区域进行调整图像尺寸的操作,来输出到目标图像中,若目标图像设置了ROI区域,会将原图像进行尺寸调整并填充到目标图像的ROI中。很多时候并不用考虑第二个参数dst的初始图像尺寸和类型。
-
6.6.6、图像金字塔相关API函数
-
pyrUpO函数的作用是向上来样并模糊一张图像,说白了就是放大一张图片。
-
void pyrUp(InputArray src, OutputArraydst, const Size& dstsize=Size( ) , int borderType=BORDER_DEFAULT )
1:输入图像;2:输出图像;3:输出图像大小,默认值Size(src.cols*2, src.rows*2);4:边界模式
-
int main() { Mat srcImage = imread("1.jpg); Mat tmpImgae = srcImage; imshow("【原始图】",srcImage); pyrUp(tmpImage, dstImage, Size(tmpImage.cols*2, tmpImage.rows*2)); imshow("【效果图】",dstImage); waitKey(0); return 0; }
-
- pyrDownO函数的作用是向下采样并模糊-张图片,说白了就是缩小 a怅图片。
-
void pyrDown (InputArray src,OutputArray dst, const Size& dstsize=Size () , int borderType=BORDER DEFAULT)
1:输入图像;2:输出图像;3:输出图像大小,默认值Size((src.cols+1)/2, (src.rows+1)/2);4:边界模式
-
int main() { Mat srcImage = imread("1.jpg"); Mat tmpImage, dstImage; tmpImage = srcImage; imshow("【原始图】",srcImage); pyrDown(tmpImage, dstImage, Size(tmpImage.cols/2,tmpImage.rows/2)); imshow("【效果图】",dstImage); waitKey(0); return 0; }
-
-
6.6.7、图像金字塔与图片尺寸缩放
-
#define WINDOW_NAME "【程序窗口】" Mat g_srcImage, g_dstImage,g_tmpImage; int main() { g_srcImage = imread("1.jpg");//尺寸需被2的N次方整除,N为缩放的次数 if(!g_srcImage.data){printf("读取srcImage错误"); return false;} namedWindow(WINDOW_NAME,WINDOW_AUTOSIZE); imshow(WINDOW_NAME,g_srcImage); //参数赋值 g_tmpImage = g_srcImage; g_dstImage = g_tmpImage; int key =0; //轮询获取按键信息 while(1) { key = waitKey(9);//读取键值到key中 //根据key值,进行不同操作 switch (key) { //-----------------程序退出键值处理---------------------- case 27://esc return 0; break; case 'q': return 0; break; //-------------------图像放大------------------------------------ case 'a'://调用pyrUp pyrUp(g_tmpImage, g_dstImage,Size(g_tmpImage.cols*2,g_tmpImage.rows*2)); printf(">检测到按键 [ A ] 被按下, 开始进行基于 [ pyrUp ] 函数的图片放大:图片尺寸x2 \n"); break; case 'w'://调用resize函数 resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols*2,g_tmpImage.rows*2)); printf ( ">检测到按键 [ w ] 被接下.开始进行基于 [ resize ] 函数的图片放大:图片尺寸x2 \n" ); break; case '1'://调用resize resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols*2,g_tmpImage.rows*2)); printf ( ">检测到按键 [ 1 ] 被接下.开始进行基于 [ resize ] 函数的图片放大:图片尺寸x2 \n" ); break; case '3'://调用pyrUp pyrUp(g_tmpImage, g_dstImage,Size(g_tmpImage.cols*2,g_tmpImage.rows*2)); printf(">检测到按键 [ 3 ] 被按下, 开始进行基于 [ pyrUp ] 函数的图片放大:图片尺寸x2 \n"); break; //--------------------------------图像缩小------------------------------------------- case 'd'://调用pyrDown pyrDown(g_tmpImage, g_dstImage, Size(g_tmpImage.cols/2, g_tmpImage.rows/2)); printf( ">检测到按键 [ 0 ] 被按下,开始进行基于 [ pyrDown ] 函数的图片缩小:图片尺寸/2\n" ); break; case 's'://resize resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols/2, g_tmpImage.rows/2)); printf ( " >检测到按键 [ S ] 被按下,开始进行基于 [ resize ] 函数的图片 缩小: 图片尺寸/2\n" ); break; case '2'://size resize(g_tmpImage, g_dstImage, Size(g_tmpImage.cols/2, g_tmpImage.rows/2),(0,0),(0,0),2); printf ( " >检测到按键 [ 2 ] 被按下,开始进行基于 [ resize ] 函数的图片 缩小: 图片尺寸/2\n" ); break; case '4'://pyrDown pyrDown(g_tmpImage, g_dstImage, Size(g_tmpImage.cols/2, g_tmpImage.rows/2)); printf( ">检测到按键 [ 4 ] 被按下,开始进行基于 [ pyrDown ] 函数的图片缩小:图片尺寸/2\n" ); break; } imshow(WINDOW_NAME,g_dstImage); //将 g_dstlmage 赋给 g_tmplmage,方俊下一次循环 g_tmpImage = g_dstImage; } return 0; }
-
-
-
6.7、阈值化
- Threshold()函数(基本阔值操作) 和 adaptiveThresholdO 函数(自适应阔值操作)可以完成这样的要求。 它们的基本思想是:给定一个数 组和一个阀值,然后根据数组中的每个元素的值是高于还是低于|凋值而进行一些 处理。
-
6.7.1、固定阈值操作:Threshold()函数
- 函数Threshold对单通道数组应用固定阈值操作。典型应用是对灰度图像进行阈值操作得到二值图像。或者是去掉噪声。
-
double threshold(InputArray src, OutputArray dst, double thresh, double maxval, int type)
1:输入数组,单通道; 2:函数调用后的运算结果,即输出结果; 3:阈值的具体值; 4:当第五个参数阔值类型 type 取 cv n议ESH BINARY 或 CV-THRESH-BDJARY-卧何时|词值类型时的 最大值; 5:阈值类型
-
- 函数Threshold对单通道数组应用固定阈值操作。典型应用是对灰度图像进行阈值操作得到二值图像。或者是去掉噪声。
-
6.7.2、自定义阈值操作:adaptiveThreshold()
-
void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int blockSize, double C)
1:输入图像; 2:输出图像; 3:给像素赋的满足条件的非零值; 4:用于指定要使用的自适应阈值算法。可取值为ADAPTIVE_THRESH_MEAN_C或ADAPTIVE_THRESH_GAUSSIAN_C; 5:阈值类型,必须是THRESH_BINARY、 THRESH_BINARY_INV其中之一;6:用于计算阈值大小的一个像素的邻域尺寸,取值为3、5、7; 7:减去平均或加权平均值后的常数值,通常为正数。
-
当第五个参数为THRESH_BINARY时:
- 当第五个参数为THRESH_BINARY_INV:
- 其中T(x,y)为分别计算每个单独像素的阈值,取值如下:
- 对于 ADAPTIVE_THRESH_MEAN_C方法, T(x,y)为 blockSize * blockSize 邻域内以(x, y) 减去第七个参数 C 的平均值。
- ADAPTIVE_THRESH_GAUSSIAN_C, T(x,y)为 blockSize * blockSize 邻域内以(x, y) 减去第七个参数 C与高斯窗交叉相关的加权总和
- 其中T(x,y)为分别计算每个单独像素的阈值,取值如下:
-
- 6.7.3、综合示例
-
#define WINDOW_NAME "【程序窗口】" int g_nThresholdValue = 100; int g_nThresholdType = 3; Mat g_srcImage, g_grayImage, g_dstImage; static void ShowHelpText(); void on_Threshold(int , void*);//回调函数 int main() { g_srcImage = imread("q.jpg"); if(!g_srcImage.data){printf("读取srcImage错误"); return false;} //存留一份原图的灰度图 cvtColor (g_srcImage, g_grayImage, COLOR_RGB2GRAY); namedWindow(WINDOW_NAME,WINDOW_AUTOSIZE); //滑动滑动条来控制阈值 createTrackbar("模式",WINDOW_NAME, &g_nThresholdType,4,on_Threshold); createTrackbar("参数值",WINDOW_NAME, &g_nThresholdValue,255,on_Threshold); //初始化自定义的回调函数 on_Threshold(0,0); //等待用户按键,esc退出 while (1) { int key; key = waitKey(20); if((char)key == 27){break;} } } void on_Threshold(int,void *) { threshold(g_grayImage, g_dstImage, g_nThresholdValue, 255 .g_nThresholdType); imshow(WINDOW_NAME,g_dstImage); }
-
- 6.8、总结
-