Opencv复习笔记

Opencv复习笔记

整理自:https://blog.csdn.net/u013162035/article/details/79645331

0.索引:

        【1】图像混合

        【2】图像通道的分离和合并

        【3】图像的翻转

        【4】图像的位运算

        【5】图像边界扩充

        【6】图像的傅里叶变化

        【7】图像归一化

        【8】计算运行时间

        【9】线性滤波

        【10】非线性滤波

        【11】形态学膨胀和腐蚀

        【12】形态学开运算、闭运算、形态学梯度、顶帽、黑帽

        【13】漫水填充

        【14】鼠标回调

        【15】图像的上采样和下采样

        【16】阈值化

        【17】边缘检测

        【18】霍夫变换

        【19】重映射

        【20】仿射变换

        【21】复制图像通道

        【22】直方图处理

        【23】模板匹配

        【24】轮廓的查找与绘制

        【25】凸包查找

        【26】轮廓形状转换

        【27】图像的矩

        【28】轮廓面积/长度计算

        【29】图论分割

        【30】角点检测

        【31】自适应滤波器

        【32】透视变换

1.图像混合:

(1)定义ROI的两种方式:

         1)Rect:

              指定矩形的左上角坐标和矩形的长宽来定义一个矩形区域。

Mat imageROI;  
imageROI=image(Rect(500,250,logo.cols,logo.rows));  

         2)Range:

               指定感兴趣行或列的范围,Range是指从起始索引到终止索引(不包括终止索引)的一连段连续序列。

imageROI=srcImage3(Range(250,250+logoImage.rows),Range(200,200+logoImage.cols));  

(2)图像线性混合:

C++: void addWeighted(InputArray src1,  double alpha,  InputArray src2,  double beta,  double gamma,  OutputArray dst,  int dtype=-1)
【参数】 
1、InputArray类型的src1,表示需要加权的第一个数组,常常填一个Mat。 
2、alpha,表示第一个数组的权重 
3、src2,表示第二个数组,它需要和第一个数组拥有相同的尺寸和通道数。 
4、beta,表示第二个数组的权重值。 
5、gamma,一个加到权重总和上的标量值。看下面的式子自然会理解。 
6、dst,输出的数组,它和输入的两个数组拥有相同的尺寸和通道数。 
7、dtype,输出阵列的可选深度,有默认值-1。;当两个输入数组具有相同的深度时,这个参数设置为-1(默认值),即等同于src1.depth()。 

(3)图像混合举例:

bool  ROI_LinearBlending()
{
    //读取图像
    Mat srcImage4= imread("pa.jpg",1);
    Mat logoImage= imread("logo.jpg");

    //定义一个Mat类型并给其设定ROI区域
    Mat imageROI;
    imageROI= srcImage4(Rect(200,250,logoImage.cols,logoImage.rows));

    //将logo加到原图上
    addWeighted(imageROI,0.5,logoImage,0.3,0.,imageROI);


    //显示结果
    imshow("Window1",srcImage4);
    return true;
}

2.图像通道的分离和合并:

(1)分离多通道:

//1.
void split(const Mat& src, Mat*mvbegin);  
//2.
void split(InputArray m,OutputArrayOfArrays mv);  

【参数】:
1、InputArray类型的m或者const Mat&类型的src,需要进行分离的多通道数组。 
2、OutputArrayOfArrays类型的mv,函数的输出数组或者输出的vector容器。

(2)合并多通道;

两个函数原型:
void merge(const Mat* mv, size_tcount, OutputArray dst)  
void merge(InputArrayOfArrays mv, OutputArray dst)  

【参数】
1,mv:需要被合并的输入矩阵或vector容器的阵列,这个mv参数中所有的矩阵必须有着一样的尺寸和深度;
2,count:当mv为一个空白的C数组时,代表输入矩阵的个数,这个参数显然必须大于1;
3,dst:输出矩阵,和mv[0]拥有一样的尺寸和深度,并且通道的数量是矩阵阵列中的通道的总数。 

(3)示例:

//准备局部变量
vector<Mat> channels;  
Mat imageBlueChannel;  
Mat imageGreenChannel;  
Mat imageRedChannel;  
//读图
srcImage4= imread("dota.jpg");  
// 通道分离
split(srcImage4,channels);
//分别读取各个通道处理结果
imageBlueChannel = channels.at(0);  
imageGreenChannel = channels.at(1);  
imageRedChannel = channels.at(2);  

3.图像的翻转:

void flip(InputArray src, OutputArray dst, int flipCode)

【参数】:
1、src:输入的矩阵; 
2、dst:输出与输入相同尺寸和类型的矩阵; 
3、flipCode:指定旋转的标志; 
             0意味着翻转x轴;
             正值(例如,1)意味着翻转y轴;
             负值(例如,- 1)意味着在两个轴上翻转。

4.图像的位运算:

        图像的位操作等同于二进制的0、1操作,Opencv中提供bitwise_not,bitwise_xor,bitwise_or,bitwise_and等函数,以图像反转函数bitwise_not为例。

void bitwise_not(InputArray src,  OutputArray dst,  InputArray mask=noArray())

【参数】:
1、src:输入的图像;
2、dst:输出与输入相同大小和类型的图像;
3、mask:可选的操作掩膜。

5.图像边界扩充:

void copyMakeBorder(InputArray src, OutputArray dst, int top, int bottom, int left, int right, int borderType, const Scalar& value=Scalar() )

【参数】:
1、src :原图像; 
2、dst :输出图像,和src有同样的类型,并且size应该是(src.cols+left+right,src.rows+top+bottom); 
3/4/5/6、top 、bottom、left 、right:这四个参数风别表示在源图像的四个方向上分别扩充多少像素,例如top=1, bottom=1, left=1, right=1 意味着在源图像的上下左右各扩充一个像素宽度的边界;
7、borderType:边界类型; 
8、value:边界值,如果borderType==BORDER_CONSTANT则用到这个参数。 

6.图像傅里叶变换:

        图像傅立叶变换就是将它分解成正弦和余弦两部分,也就是将图像从空间域(spatial domain)转换到频域(frequency domain)。这一转换的理论基础来自于以下事实:任一函数都可以表示成无数个正弦和余弦函数的和的形式。

        对于一幅图像,高频部分代表了图像的细节、纹理信息;低频部分代表了图像的轮廓信息。傅里叶变换在图像处理中可以做到:图像增强与图像去噪,图像分割之边缘检测,图像特征提取,图像压缩等等。

(1)图像傅里叶变换函数:

         图像的傅里叶变换参考https://blog.csdn.net/qq_29462849/article/details/80995335

void dft(InputArray src, OutputArray dst, int flags=0, int nonzeroRows=0)

【参数】:
1、src:输入图像; 
2、dst:输出图像; 
3、flags:转换标志,取值包括:DFT_INVERSE /DFT_SCALE /DFT_ROWS /DFT_COMPLEX_OUTPUT /DFT_REAL_OUTPUT等;
          DFT_INVERSE:执行一维或2D逆转换,而不是默认的正向转换;
          DFT_SCALE:对结果进行缩放---将其除以数组元素的数量,通常它与DFT_INVERSE组合在一起;
          DFT_ROWS:对输入矩阵的每一行执行正向或反向转换,此标志使能够同时转换多个向量,并可用于减少执行3D和高维转换等的开销;
          DFT_COMPLEX_OUTPUT:执行一维或二维实数组的前向转换;
          DFT_REAL_OUTPUT:执行一维或二维复杂数组的反向转换;
4、nonzeroRows:当参数不为零时,函数假设只有输入数组的第一个nonzeroRows行(没有设置DFT_INVERSE)或只有输出数组的第一个nonzeroRows行(设置了DFT_INVERSE)包含非零,因此函数可以更有效地处理其余的行并节省一些时间,这个技术对于用DFT计算阵列的互相关或卷积非常有用。

(2)返回指定向量的傅里叶最优尺寸大小:

         为了提高离散傅立叶变换的运行速度,需要扩充图像及扩充的尺寸由这个函数计算得到。通常后接图像边界扩充函数copyMakeBorder()。

int getOptimalDFTSize(int vecsize)

【参数】:
1、vecsize:向量尺寸,即图片的rows,cols。

(3)计算二维矢量的幅值:

void magnitude(InputArray x, InputArray y, OutputArray magnitude)

【参数】:
1、x:实部 ;
2、y:虚部,size和x一样 ;
3、magnitude:输出图像,和x有同样的size和type。

(4)计算对数:

void log(InputArray src, OutputArray dst)

【参数】:
1、src:输入图像 ;
2、dst:输出图像。

7.图像归一化:

void normalize(const InputArray src, OutputArray dst, double alpha=1, double beta=0, int normType=NORM_L2, int rtype=-1, InputArray mask=noArray())

【参数】:
1、src:输入矩阵; 
2、dst:输出矩阵 ;
3、alpha:归一化后的最大值 ;
4、beta:归一化后的最小值 ;
5、norm_type:归一化类型,有NORM_INF, NORM_L1, NORM_L2和NORM_MINMAX 
6、rtype:当参数为负时,目标数组的类型与src相同;否则,它拥有与src相同数量的通道和depth。

8.计算运行时间:

double Time = (double)cvGetTickCount();
SelectShapeProto(imagepanel, Threshold, imageResult, 100, 100000000);
Time = (double)cvGetTickCount() - Time;
printf("run time = %gs\n", Time / (cvGetTickFrequency() * 1000000));//秒

9.线性滤波:

        函数的源码及解析参考https://blog.csdn.net/u013162035/article/details/78487475

(1)方框滤波:

          非归一化的方框滤波用于计算每个像素邻域内的积分特性,比如密集光流算法(dense optical flow algorithms)中用到的图像倒数的协方差矩阵。

void boxFilter(InputArray src,OutputArray dst, int ddepth, Size ksize, Point anchor=Point(-1,-1), boolnormalize=true, int borderType=BORDER_DEFAULT )  

【参数】:
1、src:输入图像,Mat类的对象。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一; 
2、dst:目标图像,需要和源图片有一样的尺寸和类型;
3、ddepth:输出图像的深度,-1代表使用原图深度,即src.depth(); 
4、ksize:内核的大小。一般用Size( w,h )来表示内核的大小( 其中,w 为像素宽度, h为像素高度),如Size(3,3)就表示3x3的核大小。
5、Point类型的anchor:表示锚点(即被平滑的那个点),注意它有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心; 
6、normalize:默认值为true,一个标识符,表示内核是否被其区域归一化(normalized); 
7、borderType:用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT。

(2)均值滤波:

          均值滤波是方框滤波归一化(normalized)后的特殊情况。

void blur(InputArray src, OutputArraydst, Size ksize, Point anchor=Point(-1,-1), int borderType=BORDER_DEFAULT )  

【参数】:
1、src:输入图像,Mat类的对象。该函数对通道是独立处理的,且可以处理任意通道数的图片,但需要注意,待处理的图片深度应该为CV_8U, CV_16U, CV_16S, CV_32F 以及 CV_64F之一。 
2、dst:目标图像,需要和源图片有一样的尺寸和类型。
3、Size类型的ksize,内核的大小。一般用Size( w,h )来表示内核的大小,如Size(3,3)就表示3x3的核大小;
4、anchor,表示锚点(即被平滑的那个点),注意有默认值Point(-1,-1)。如果这个点坐标是负值的话,就表示取核的中心为锚点,所以默认值Point(-1,-1)表示这个锚点在核的中心。 
5、borderType:用于推断图像外部像素的某种边界模式,有默认值BORDER_DEFAULT。 

(3)高斯滤波:

          高斯滤波的解析参考https://blog.csdn.net/syp1992223/article/details/80233842

void GaussianBlur(InputArray src,OutputArray dst, Size ksize, double sigmaX, double sigmaY=0, intborderType=BORDER_DEFAULT)  

【参数】:
1、src,输入图像,即源图像;
2、dst,目标图像,需要和源图片有一样的尺寸和类型;
3、ksize:高斯内核的大小。其中ksize.width和ksize.height可以不同,但他们都必须为正数和奇数或者零,它们都是由sigma计算而来;
4、sigmaX:表示高斯核函数在X方向的的标准偏差;
5、sigmaY:表示高斯核函数在Y方向的的标准偏差。若sigmaY为零,就将它设为sigmaX;如果sigmaX和sigmaY都是0,那么就由ksize.width和ksize.height计算出来。最好把第三个参数Size,第四个参数sigmaX和第五个参数sigmaY全部指定。 
6、borderType:边界模式。

(4)图像卷积运算函数滤波:

         该函数使用于任意线性滤波器的图像,当其中心移动到图像外,函数可以根据指定的边界模式进行插值运算。

void filter2D( InputArray _src, OutputArray _dst, int ddepth, InputArray _kernel, Point anchor0, double delta, int borderType ) 

【参数】: 
1、InputArray src: 输入图像 ;
2、OutputArray dst: 输出图像,和输入图像具有相同的尺寸和通道数量 ;
3、ddepth: 目标图像深度,当ddepth输入值为-1时,目标图像和原图像深度保持一致。如果没写将生成与原图像深度相同的图像,原图像和目标图像支持的图像深度如下: 
               src.depth() = CV_8U, ddepth = -1/CV_16S/CV_32F/CV_64F 
               src.depth() = CV_16U/CV_16S, ddepth = -1/CV_32F/CV_64F 
               src.depth() = CV_32F, ddepth = -1/CV_32F/CV_64F 
               src.depth() = CV_64F, ddepth = -1/CV_64F 
4、kernel: 卷积核(或者是相关核),一个单通道浮点型矩阵。如果想在图像不同的通道使用不同的kernel,可以先使用split()函数将图像通道事先分开。 
5、anchor: 内核的基准点(anchor),其默认值为(-1,-1)说明位于kernel的中心位置。基准点即kernel中与进行处理的像素点重合的点。 
6、delta: 在储存目标图像前可选的添加到像素的值,默认值为0 
7、borderType: 像素向外逼近的方法,默认值是BORDER_DEFAULT,即对全部边界进行计算。 

10.非线性滤波:

(1)中值滤波:

          中值滤波花费的时间是均值滤波的5倍以上,一般采用奇数点的邻域来计算中值,但如果像素点数为偶数时,中值就取排序像素中间两点的平均值。中值滤波在一定条件下,可以克服线性滤波器所带来的图像细节模糊,但是对一些细节多的图像不宜采用中值滤波。

void medianBlur(InputArray src,OutputArray dst, int ksize)  

【参数】 
1、src:函数的输入参数,1、3或者4通道的Mat类型的图像。当ksize为3或者5的时候,图像深度需为CV_8U,CV_16U,或CV_32F其中之一,而对于较大孔径尺寸的图片,它只能是CV_8U。 
2、dst:目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。
3、ksize:孔径的线性尺寸,这个参数必须是大于1的奇数,比如:3,5,7,9 … 。

(2)双边滤波:

         双边滤波的原理解析参考https://blog.csdn.net/u013921430/article/details/84532068

         双边滤波是结合图像的空间邻近度和像素值相似度的一种折中处理,同时考虑空域信息和灰度相似性,达到保边去噪的目的,具有简单、非迭代、局部的特点。

         双边滤波器的好处是可以做边缘保存,它是基于空间分布的高斯滤波函数,所以离的较远的像素不会太多影响到边缘上的像素值,这样就保证了边缘附近像素值的保存。

void bilateralFilter(InputArray src,OutputArraydst,int d, double sigmaColor, double sigmaSpace, int borderType=BORDER_DEFAULT)  

【参数】 
1、src,输入图像,需要为8位或者浮点型单通道、三通道的图像;
2、dst,目标图像,需要和源图片有一样的尺寸和类型;
3、d:表示在过滤过程中每个像素邻域的直径。如果这个值设为非正数,那么OpenCV会从第五个参数sigmaSpace来计算它; 
4、sigmaColor:颜色空间滤波器的sigma值。这个参数的值越大,就表明该像素邻域内有更宽广的颜色会被混合到一起,产生较大的半相等颜色区域; 
5、sigmaSpace:坐标空间中滤波器的sigma值,坐标空间的标注方差。数值越大,意味着越远的像素会相互影响,从而使更大的区域足够相似的颜色获取相同的颜色。
               当d>0,d指定了邻域大小且与sigmaSpace无关;否则,d正比于sigmaSpace;
6、borderType:边界模式。

11.形态学膨胀和腐蚀:

(1)获取结构元素:

         一般在调用erode()及dilate()函数之前,需要先定义一个Mat类型的变量来获得getStructuringElement()函数的返回值,后续调用erode()及dilate()函数时第三个参数保存了getStructuringElement返回值的Mat类型变量。

//定义结构元素(内核矩阵)的尺寸 
int g_nStructElementSize = 3;  
//获取自定义核  
Mat element =getStructuringElement(MORPH_RECT,Size(2*g_nStructElementSize+1,2*g_nStructElementSize+1),  Point( g_nStructElementSize, g_nStructElementSize ));  

【参数】:
1、内核的形状,可以选择如下三种形状之一:矩形MORPH_RECT、交叉形MORPH_CROSS、椭圆形MORPH_ELLIPSE;2、内核的尺寸;
3、锚点的位置,有默认值Point(-1,-1),表示锚点位于中心。需要注意,十字形的element形状唯一依赖于锚点的位置,而在其他情况下锚点只是影响了形态学运算结果的偏移。

(2)形态学膨胀:

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、src:输入图像,Mat类的对象。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一。 
2、dst:即目标图像,需要和源图片有一样的尺寸和类型。 
3、kernel:膨胀操作的核。若为NULL时,表示的是使用参考点位于中心3x3的核,一般使用函数 getStructuringElement配合这个参数的使用;
4、anchor:锚的位置,其有默认值(-1,-1),表示锚位于中心; 
5、iterations:迭代使用erode()函数的次数,默认值为1; 
6、borderType:边界模式,默认值为BORDER_DEFAULT;
7、borderValue:当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般不管这个参数。
使用dilate函数,一般只需要注意前面的三个参数,后面的四个参数都有默认值。

(3)形态学腐蚀:

void erode(InputArray src, OutputArray dst, InputArray kernel, Point anchor=Point(-1,-1),  int iterations=1, int borderType=BORDER_CONSTANT,const Scalar& borderValue=morphologyDefaultBorderValue() );  

【参数】:
1、src:输入图像,Mat类的对象。图像通道的数量可以是任意的,但图像深度应为CV_8U,CV_16U,CV_16S,CV_32F或 CV_64F其中之一;
2、dst:目标图像,需要和源图片有一样的尺寸和类型;
3、kernel:腐蚀操作的内核,若为NULL时,表示的是使用参考点位于中心3x3的核,一般使用函数 getStructuringElement配合这个参数的使用;
4、anchor:锚的位置,其有默认值(-1,-1),表示锚位于单位(element)的中心,一般不用管它;
5、iterations:迭代使用erode()函数的次数,默认值为1; 
6、borderType:边界模式,默认值BORDER_DEFAULT;
7、borderValue,当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般不去管它;

12.形态学开运算、闭运算、形态学梯度、顶帽、黑帽:

void morphologyEx( InputArray src, OutputArray   dst, int op, InputArray kernel, Pointanchor=Point(-1,-1), int iterations=1, int borderType=BORDER_CONSTANT, constScalar& borderValue=morphologyDefaultBorderValue() );  

【参数】:
1、src:输入图像,Mat类的对象。图像位深应该为以下五种之一:CV_8U, CV_16U,CV_16S, CV_32F 或CV_64F;
2、dst:目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型。 
3、op:表示形态学运算的类型,可以是如下之一的标识符: 
     MORPH_OPEN – 开运算(Opening operation) 
     MORPH_CLOSE – 闭运算(Closing operation) 
     MORPH_GRADIENT -形态学梯度(Morphological gradient) 
     MORPH_TOPHAT - “顶帽”(“Top hat”) 
     MORPH_BLACKHAT - “黑帽”(“Black hat“) 
4、kernel:形态学运算的内核,若为NULL时,表示的是使用参考点位于中心3x3的核;一般使用函数 getStructuringElement配合这个参数的使用。
5、anchor:锚的位置,其有默认值(-1,-1),表示锚位于中心;
6、iterations:迭代使用函数的次数,默认值为1;
7、borderType:边界模式;
8、borderValue:当边界为常数时的边界值,有默认值morphologyDefaultBorderValue(),一般不去管它。

(1)开运算:

         开运算为先腐蚀后膨胀,功能是可以用来消除小物体、在纤细点处分离物体、平滑较大物体的边界的同时并不明显改变其面积。

(2)闭运算:

         闭运算为先膨胀后腐蚀,闭运算的功能是排除小型黑洞(黑色区域)。

(3)形态学梯度:

         形态学梯度为膨胀图与腐蚀图之差,对二值图像进行这一操作可以将团块(blob)的边缘突出出来,可以用形态学梯度来保留物体的边缘轮廓。

(4)顶帽运算:

         顶帽运算为原图像与开运算的结果图之差,顶帽运算得到的效果图突出了比原图轮廓周围的区域更明亮的区域,且这一操作和选择的核的大小相关。

         顶帽运算往往用来分离比邻近点亮一些的斑块,当一幅图像具有大幅的背景的时候,而微小物品比较有规律的情况下,可以使用顶帽运算进行背景提取。

(5)黑帽运算:

         黑帽运算为闭运算的结果图与原图像之差,黑帽运算后的效果图突出了比原图轮廓周围的区域更暗的区域,且这一操作和选择的核的大小相关。

         黑帽运算通常用来分离比邻近点暗一些的斑块。

13.漫水填充:

        关于漫水填充算法的解析参考https://blog.csdn.net/u013162035/article/details/78504951(关于这个API主观认为在工业检测上没有任何用得到的场景)。

        漫水填充算法查找和种子点联通的颜色相同的点,自动选中了和种子点相连的区域(连通性由像素值的接近程度来衡量),接着将该区域替换成指定的颜色,经常用来标记或者分离图像的一部分进行处理或分析,也可以用来从输入图像获取掩码区域。

//版本1:
int floodFill(InputOutputArray image, Point seed, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 )

//版本2(参数2有差别):
int floodFill(InputOutputArray image, InputOutputArray mask, Point seed, Scalar newVal, Rect* rect=0, Scalar loDiff=Scalar(), Scalar upDiff=Scalar(), int flags=4 )

【参数】:
1、image:输入/输出1通道或3通道、8位或浮点图像,具体参数由后面参数指明;
2、mask:操作掩模,这是版本2特有的参数,应为单通道、8位、长和宽上都比输入图像大两个像素点的图像。版本2需要使用以及更新掩膜,所以这个mask参数一定要将其准备好并填在此处。需要注意的是:
         1)漫水填充不会填充掩膜mask的非零像素区域。例如,一个边缘检测算子的输出可以用来作为掩膜,以防止填充到边缘。同样也可以在多次的函数调用中使用同一个掩膜,以保证填充的区域不会重叠。
         2)掩膜mask会比需填充的图像大,所以 mask 中与输入图像(x,y)像素点相对应的点的坐标为(x+1,y+1)。 
3、seedPoint:漫水填充算法的起始点;
4、newVal:像素点被染色的值;
5、rect:有默认值0,可选的参数,用于设置floodFill函数将要重绘区域的最小边界矩形区域;
6、loDiff:有默认值Scalar( ),表示当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之负差的最大值;
7、upDiff,有默认值Scalar( ),表示当前观察像素值与其部件邻域像素值或者待加入该部件的种子像素之间的亮度或颜色之正差的最大值;
8、flags:操作标志符,此参数包含三个部分:
         1)低八位(第0~7位):用于控制算法的连通性,可取4 (4为缺省值) 或者 8。如果设为4,表示填充算法只考虑当前像素水平方向和垂直方向的相邻点;如果设为8,除上述相邻点外,还会包含对角线方向的相邻点;
         2)高八位部分(16~23位):可以为0或者如下两种选项标识符的组合: 
            FLOODFILL_FIXED_RANGE:设置本标识符考虑当前像素与种子像素之间的差,否则就考虑当前像素与其相邻像素的差;
            FLOODFILL_MASK_ONLY:设置本标识符函数不会去填充改变原始图像 (忽略第三个参数newVal), 而是去填充掩模图像(mask)。这个标识符只对版本2有用,因第一个版本里面压根就没有mask参数;
         3)中间八位部分:用于指定填充掩码图像的值。如果中间八位的值为0,则掩码会用1来填充。 
         所有flags可以用or操作符---“|”连接起来。例如,如果想用8邻域填充,并填充固定像素值范围,填充掩码而不是填充源图像,以及设填充值为38,那么输入的参数是这样: flags=8 |FLOODFILL_MASK_ONLY | FLOODFILL_FIXED_RANGE | (38<<8) 

14.鼠标回调:

void setMouseCallback(conststring& winname,MouseCallback onMouse, void* userdata=0 )  

【参数】:
1、winname:窗口名字;
2、onMouse:指定窗口里每次鼠标时间发生的时候,被调用的函数指针。
            函数原型应该为voidFoo(int event, int x, int y, int flags, void* param);
            其中event是 CV_EVENT_*变量之一, x和y是鼠标指针在图像坐标系的坐标(不是窗口坐标系),flags是CV_EVENT_FLAG的组合, param是用户定义的传递到cvSetMouseCallback函数调用的参数。 
3、userdata:用户定义的传递到回调函数的参数,有默认值0。

15.图像的上采样和下采样:

        高斯金字塔: 用来向下采样;
        拉普拉斯金字塔: 用来从金字塔低层图像重建上层未采样图像,在数字图像处理中也即是预测残差,可以对图像进行最大程度的还原。

        这里的向下与向上采样,是对图像的尺寸而言的(和金字塔的方向相反),向上就是图像尺寸加倍,向下就是图像尺寸减半。

(1)图像上采样:

         图像上采样执行高斯金字塔的采样操作,作用是向上采样并模糊一张图像,即放大一张图片。首先,它通过插入可为零的行与列,对源图像进行向上取样操作,然后将结果与pyrDown()乘以4的内核做卷积。

void pyrUp(InputArray src, OutputArraydst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT )  

【参数】:
1、src,输入图像,Mat类的对象。 
2、dst,输出图像,和源图片有一样的尺寸和类型;
3、dstsize:输出图像的大小,有默认值Size(),即默认情况下,由Size(src.cols*2,src.rows*2)来进行计算。
4、borderType:边界模式。

(2)图像下采样:

         图像下采样的作用是向下采样并模糊一张图片,也就是缩小一张图片。pyrDown函数执行了高斯金字塔建造的向下采样的步骤,首先它将源图像与如下内核做卷积运算,然后它通过对图像的偶数行和列做插值来进行向下采样。

void pyrDown(InputArray src, OutputArray dst, const Size& dstsize=Size(), int borderType=BORDER_DEFAULT)  

【参数】:
1、src:输入图像,Mat类的对象;
2、dst:输出图像,和源图片有一样的尺寸和类型; 
3、dstsize:输出图像的大小;有默认值Size(),即默认情况下,由Size Size((src.cols+1)/2, (src.rows+1)/2)来进行计算;
4、borderType:边界模式。

(3)图像尺寸调整:

void resize(InputArray src,OutputArray dst, Size dsize, double fx=0, double fy=0, int interpolation=INTER_LINEAR )  

【参数】:
1、src:输入图像,可为Mat类的对象;
2、dst:输出图像,当其非零时,有着参数dsize的尺寸,或者由src.size()计算出来;
3、dsize:输出图像的大小; 
4、fx:沿水平轴的缩放系数,有默认值0,当其等于0时可计算得出: 
5、fy:沿垂直轴的缩放系数,有默认值0,当其等于0时可计算得出: 
6、interpolation:指定插值方式,默认为INTER_LINEAR(线性插值)。可选的插值方式如下: 
                  INTER_NEAREST:最近邻插值 
                  INTER_LINEAR:线性插值(默认值) 
                  INTER_AREA:区域插值(利用像素区域关系的重采样插值) 
                  INTER_CUBIC:三次样条插值(超过4×4像素邻域内的双三次插值) 
                  INTER_LANCZOS4:Lanczos插值(超过8×8像素邻域的Lanczos插值) 
                  若要缩小图像,一般情况下最好用CV_INTER_AREA来插值;而若要放大图像,一般情况下最好用CV_INTER_CUBIC(效率不高,不推荐使用)或CV_INTER_LINEAR(效率较高,速度较快,推荐使用)。 

16.阈值化:

(1)固定阈值操作:

double threshold(InputArray src, OutputArray dst, double thresh, double maxVal, int thresholdType)

【参数】:
1、src,输入数组,可以为单通道、8或32位浮点类型的Mat。 
2、dst,函数调用后的运算结果,和第一个参数中的Mat变量有一样的尺寸和类型; 
3、thresh,阈值; 
4、maxval,当第五个参数阈值类型type取 THRESH_BINARY 或THRESH_BINARY_INV阈值类型时的最大值. 
5、type,阈值操作类型,参数包括下面几个取值:
         0:THRESH_BINARY:当前点值大于阈值时,取Maxval,否则设置为0;
         1: THRESH_BINARY_INV :当前点值大于阈值时,设置为0,否则设置为Maxval;
         2: THRESH_TRUNC :当前点值大于阈值时,设置为阈值,否则不改变;
         3: THRESH_TOZERO: 当前点值大于阈值时,不改变,否则设置为0;
         4: THRESH_TOZERO_INV: 当前点值大于阈值时,设置为0,否则不改变。

(2)自适应阈值:

          根据像素的邻域块的像素值分布来确定该像素位置上的二值化阈值,类似于Halcon中的常用函数组合mean_image+dyn_threshold。

void adaptiveThreshold(InputArray src, OutputArray dst, double maxValue, int adaptiveMethod, int thresholdType, int bolckSize, double C)  

【参数】:
1、src:输入图像,可为单通道8位浮点类型Mat。
2、dst:存放函数运算结果的输出图像,与输入图像同样的尺寸和类型;
3、maxValue:预设满足条件的最大值;
4、adaptiveMethod:指定自适应阈值算法,参数可选ADAPTIVE_THRESH_MEAN_C 或 ADAPTIVE_THRESH_GAUSSIAN_C。
5、thresholdType:指定阈值类型,参数可选THRESH_BINARY或者THRESH_BINARY_INV两种。(即二进制阈值或反二进制阈值);
6、bolckSize:邻域块大小,用来计算区域阈值,一般选择为3、5、7......等。
7、参数C:与算法有关的参数,它是一个从均值或加权均值提取的常数,可以是负数。
---------------------------------------------------------------------------------
对参数4与参数7的解释:
       自适应阈值化计算大概过程是为每一个象素点单独计算的阈值,即每个像素点的阈值都是不同的,就是将该像素点周围B*B区域内的像素加权平均,然后减去一个常数C,从而得到该点的阈值。B由参数6指定,常数C由参数7指定。
       1)ADAPTIVE_THRESH_MEAN_C,为局部邻域块的平均值,该算法是先求出块中的均值,再减去常数C;
       2)ADAPTIVE_THRESH_GAUSSIAN_C,为局部邻域块的高斯加权和,该算法是在区域中(x, y)周围的像素根据高斯函数按照距离中心点的距离进行加权计算,再减去常数C。

17.边缘检测:

(1)Canny算子:

          Canny边缘检测算子的基本流程为:高斯平滑滤波器卷积降噪;Sobel滤波器计算梯度幅值和方向;对梯度和幅值进行非极大值抑制,排除非边缘像素, 仅仅保留了一些细线条作为候选边缘;滞后阈值处理,推荐的高低阈值比在2:1到3:1之间。

void Canny(InputArray image, OutputArray edges, double threshold1, double threshold2, int apertureSize=3, bool L2gradient=false)  

【参数】:
1、image:输入图像,可为单通道8位Mat类的对象;
2、edges:输出的边缘图,需要和源图片有一样的尺寸和类型; 
3、threshold1:第一个滞后性阈值;
4、threshold2:第二个滞后性阈值,阈值1和阈值2两者的小者用于边缘连接,而大者用来控制强边缘的初始段,推荐的高低阈值比在2:1到3:1之间;
5、apertureSize:表示应用Sobel算子的孔径大小,其有默认值3; 
6、L2gradient:一个计算图像梯度幅值的标识,有默认值false。

【调用示例】: 
Mat src = imread("1.jpg");  
Canny(src, src, 3, 9 ,3 );  
imshow("Canny", src);  

(2)Sobel算子:

         Sobel算子结合了高斯平滑和微分求导,用来计算图像灰度函数的近似梯度。在图像的任何一点使用此算子将会产生对应的梯度矢量或是法矢量。

         Sobel算子的基本流程为:分别在x和y两个方向用一个奇数大小的卷积核进行卷积;在图像的每一点结合x和y方向的两个卷积结果求出近似梯度。

void Sobel ( InputArray src, OutputArray dst, int ddepth, int dx, int dy,  int ksize=3,  
double scale=1, double delta=0,int borderType=BORDER_DEFAULT );  

【参数】:
1、src:输入图像,可为Mat类型图像; 
2、dst:目标图像,函数的输出参数,需要和源图片有一样的尺寸和类型; 
3、ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合: 
         若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F 
         若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F 
         若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F 
         若src.depth() = CV_64F, 取ddepth = -1/CV_64F 
4、dx:x方向上的差分阶数; 
5、dy:y方向上的差分阶数; 
6、ksize:Sobel核的大小,有默认值3,必须取1,3,5或7; 
7、scale:计算导数值时可选的缩放因子,默认值是1表示没有应用缩放;
8、delta:表示在结果存入目标图dst之前可选的delta值,有默认值0; 
9、borderType:边界模式,默认值为BORDER_DEFAULT。


【补充说明】:
1、当内核大小为3时, Sobel内核可能产生比较明显的误差(Sobel算子只是求取了导数的近似值)。 为解决这一问题OpenCV提供了Scharr函数,该函数仅作用于大小为3的内核。
2、一般情况下,都是用ksize x ksize内核来计算导数的,然而,有一种特殊情况——当ksize为1时,往往会使用3 x 1或者1 x 3的内核,且这种情况下并没有进行高斯平滑操作。

(3)Laplacian算子:

         Laplacian算子定义为笛卡儿坐标系中的所有非混合二阶偏导数求和,是n维欧几里德空间中的一个二阶微分算子。由于 Laplacian使用了图像梯度,它内部的代码调用了 Sobel 算子,让一幅图像减去它的Laplacian可以增强对比度。

void Laplacian(InputArray src,OutputArray dst, int ddepth, int ksize=1, double scale=1, double delta=0, intborderType=BORDER_DEFAULT );  

【参数】:
1、image:输入图像,可以为单通道8位Mat类对象;
2、edges:输出的边缘图,需要和源图片有一样的尺寸和通道数; 
3、ddept:目标图像的深度;
4、ksize:用于计算二阶导数的滤波器的孔径尺寸,大小必须为正奇数,且有默认值1; 
5、scale:计算拉普拉斯值的时候可选的比例因子,有默认值1; 
6、delta:表示在结果存入目标图dst之前可选的delta值,有默认值0; 
7、borderType:边界模式,默认值为BORDER_DEFAULT。

(4)scharr滤波器:

         当内核大小为3时, Sobel内核可能产生比较明显的误差(Sobel算子只是求取了导数的近似值), 为解决这一问题OpenCV提供了Scharr函数,该函数仅作用于大小为3的内核。

void Scharr( InputArray src, OutputArray dst, int ddepth,int dx,int dy,double scale=1,double delta=0,int borderType=BORDER_DEFAULT)

【参数】:
1、src:输入图像,可为Mat类型图像;
2、dst:目标图像,需要和源图片有一样的尺寸和类型; 
3、ddepth,输出图像的深度,支持如下src.depth()和ddepth的组合: 
         若src.depth() = CV_8U, 取ddepth =-1/CV_16S/CV_32F/CV_64F 
         若src.depth() = CV_16U/CV_16S, 取ddepth =-1/CV_32F/CV_64F 
         若src.depth() = CV_32F, 取ddepth =-1/CV_32F/CV_64F 
         若src.depth() = CV_64F, 取ddepth = -1/CV_64F 
4、dx:x方向上的差分阶数; 
5、dy:y方向上的差分阶数;
6、scale:计算导数值时可选的缩放因子,默认值是1表示没有应用缩放。
7、delta:表示在结果存入目标图dst之前可选的delta值,有默认值0; 
8、borderType:边界模式,默认值为BORDER_DEFAULT。

18.霍夫变换:

        https://blog.csdn.net/u013162035/article/details/79381478

        霍夫变换运用两个坐标空间之间的变换将在一个空间中具有相同形状的曲线或直线映射到另一个坐标空间的一个点上形成峰值,从而把检测任意形状的问题转化为统计峰值问题。    

(1)霍夫线变换:

         1)霍夫变换简介:

               霍夫线变换的直接输入只能是边缘二值图像,因此在使用之前首先要对图像进行边缘检测的处理。OpenCV中的霍夫线变换有如下三种:
               <1>标准霍夫变换(StandardHough Transform,SHT),由HoughLines函数调用。
               <2>多尺度霍夫变换(Multi-ScaleHough Transform,MSHT),由HoughLines函数调用。多尺度霍夫变换是标准霍夫变换(SHT)算法的一个改进,它在一定的范围内进行霍夫变换,计算单独线段的方向以及范围,从而减少计算量,缩短计算时间。之所以称PPHT为“概率”的,是因为并不将累加器平面内的所有可能的点累加,而只是累加其中的一部分,该想法是如果峰值如果足够高,只用一小部分时间去寻找它就够了,这样可以实质性地减少计算时间。
               <3>累计概率霍夫变换(ProgressiveProbabilistic Hough Transform,PPHT),由HoughLinesP函数调用。累计概率霍夫变换执行效率很高,所有相比于HoughLines函数更倾向于使用HoughLinesP函数。

         2)霍夫变换原理:

               一条直线在图像二维空间可由两个变量表示,在笛卡尔坐标系可由参数斜率和截距(m,b) 表示;在极坐标系可由参数极径和极角表示,霍夫变换采用极坐标系来表示直线,直线的表达式可以简化为:r=xcos\Theta +ysin\Theta;

               一般来说对于点(x0,y0)可以将通过这个点的一族直线统一定义为:r0=x0∗cosθ+y0∗sinθ,这就意味着每一对(rθ,θ)代表一条通过点(x0,y0)的直线;

               如果对于一个给定点(x0,y0)我们在极坐标对极径极角平面绘出所有通过它的直线, 将得到一条正弦曲线如果对图像中所有的点进行这个操作。如果两个不同点进行上述操作后得到的曲线在平面θ-r相交, 这就意味着它们通过同一条直线,越多曲线交于一点也就意味着这个交点表示的直线由更多的点组成;

               霍夫线变换追踪图像中每个点对应曲线间的交点. 如果交于一点的曲线的数量超过了阈值, 那么可以认为这个交点所代表的参数对(θ,r_θ)在原图像中为一条直线。

         3)霍夫变换API:

(1)标准霍夫变换SHT和多尺度霍夫变换MSHT:
void HoughLines(InputArray image,  OutputArray lines,  double rho,  double theta,  int threshold,  double srn=0,  double stn=0 )  

【参数】:
1、image,输入图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后再输入进来;
2、lines:经过调用HoughLines函数后储存了霍夫线变换检测到线条的输出矢量。每一条线由具有两个元素的矢量表示:离坐标原点((0,0)(也就是图像的左上角)的距离和弧度线条旋转角度(0~垂直线,π/2~水平线);
3、rho:以像素为单位的距离精度,即直线搜索时的进步尺寸的单位半径;
4、theta:以弧度为单位的角度精度,即直线搜索时的进步尺寸的单位角度;
5、threshold:累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值。大于阈值threshold的线段才可以被检测通过并返回到结果中;
6、srn:对于多尺度的霍夫变换,这是第三个参数进步尺寸rho的除数距离,有默认值0。粗略的累加器进步尺寸直接是第三个参数rho,而精确的累加器进步尺寸为rho/srn; 
7、stn:对于多尺度霍夫变换,srn表示第四个参数进步尺寸的单位角度theta的除数距离,有默认值0。如果srn和stn同时为0,就表示使用经典的霍夫变换。否则,这两个参数应该都为正数。


(2)累计概率霍夫变换PPHT:
void HoughLinesP(InputArray image, OutputArray lines, double rho, double theta, int threshold, double minLineLength=0, double maxLineGap=0 )  

【参数】:
1、image,输入图像,需为8位的单通道二进制图像,可以将任意的源图载入进来后由函数修改成此格式后再输入进来;
2、lines:经过调用HoughLinesP函数后后存储了检测到的线条的输出矢量,每一条线由具有四个元素的矢量(x_1,y_1, x_2, y_2) 表示,其中,(x_1, y_1)和(x_2, y_2) 是是每个检测到的线段的结束点; 
3、rho:以像素为单位的距离精度,即直线搜索时的进步尺寸的单位半径;
4、theta:以弧度为单位的角度精度,即直线搜索时的进步尺寸的单位角度;
5、threshold:累加平面的阈值参数,即识别某部分为图中的一条直线时它在累加平面中必须达到的值,大于阈值threshold的线段才可以被检测通过并返回到结果中;
6、minLineLength,表示最低线段的长度,比这个设定参数短的线段就不能被显现出来,有默认值0;
7、maxLineGap:允许将同一行点与点之间连接起来的最大的距离,有默认值0。 

(2)霍夫圆变换:

         1)霍夫梯度法原理:

               1.首先对图像应用边缘检测,比如canny边缘检测算子。
               2.对边缘图像中的每一个非零点,考虑其局部梯度,即用Sobel()函数计算x和y方向的Sobel一阶导数得到梯度。
               3.利用得到的梯度,由斜率指定的直线上的每一个点都在累加器中被累加,这里的斜率是从一个指定的最小值到指定的最大值的距离,同时,标记边缘图像中每一个非0像素的位置。
               4.然后从二维累加器中这些点中选择候选的中心,这些中心都大于给定阈值并且大于其所有近邻,这些候选的中心按照累加值降序排列,以便于最支持像素的中心首先出现。
               5.接下来对每一个中心,考虑所有的非0像素。
               6.这些像素按照其与中心的距离排序,从到最大半径的最小距离算起,选择非0像素最支持的一条半径。

               7.如果一个中心收到边缘图像非0像素最充分的支持,并且到前期被选择的中心有足够的距离,那么它就会被保留。

          2)霍夫变换API:

void HoughCircles(InputArray image,OutputArray circles, int method, double dp, double minDist,double param1=100,double param2=100, int minRadius=0, int maxRadius=0 )  

【参数】:
1、image:输入图像,需为8位的灰度单通道图像;
2、circles:经过调用HoughCircles函数后此参数存储了检测到的圆的输出矢量,每个矢量由包含了3个元素的浮点矢量(x, y, radius)表示; 
3、method:检测方法,目前OpenCV中只有霍夫梯度法一种可以使用---CV_HOUGH_GRADIENT;
4、dp:用来检测圆心的累加器图像的分辨率于输入图像之比的倒数,且此参数允许创建一个比输入图像分辨率低的累加器。例如,如果dp=1时,累加器和输入图像具有相同的分辨率;如果dp=2,累加器便有输入图像一半那么大的宽度和高度;
5.minDist:霍夫变换检测到的圆的圆心之间的最小距离,即让算法能明显区分的两个不同圆之间的最小距离。这个参数如果太小多个相邻的圆可能被错误地检测成了一个重合的圆;反之,这个参数设置太大某些圆就不能被检测出来了;
6、param1:它是参数method设置的检测方法的对应的参数,对于霍夫梯度法CV_HOUGH_GRADIENT,它表示传递给canny边缘检测算子的高阈值,而低阈值为高阈值的一半,有默认值100; 
7、param2:它是参数method设置的检测方法的对应的参数,对于霍夫梯度法CV_HOUGH_GRADIENT,,它表示在检测阶段圆心的累加器阈值。这个参数如果太小可能检测到更多根本不存在的圆,而取值比较大能通过检测的圆就更加接近完美的圆形,默认值100;
8、minRadius:表示圆半径的最小值,有默认值0;
9、maxRadius:表示圆半径的最大值,也有默认值0。 
需要注意的是,使用此函数可以很容易地检测出圆的圆心,但是它可能找不到合适的圆半径。

19.重映射:

        重映射就是把一幅图像中某位置的像素放置到另一幅图片指定位置的过程,重映射函数会根据指定的映射形式将源图像进行重映射几何变换。由于源图像与目标图像的像素坐标不是一一对应的,为了完成映射过程需要获得一些插值为非整数像素的坐标。

void remap(InputArray src, OutputArraydst, InputArray map1, InputArray map2, int interpolation, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())  

【参数】:
1、src:输入图像,可为单通道8位或者浮点型图像的Mat类的对象; 
2、dst:输出结果,需和源图片有一样的尺寸和类型;
3、map1:它有两种可能的表示对象:
       1)表示点(x,y)的第一个映射;
       2)表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值;
4、map2:它有两种可能的表示对象,而且它是根据map1来确定表示哪种对象: 
       1)若map1表示点(x,y)时。这个参数不代表任何值;
       2)表示CV_16UC1 , CV_32FC1类型的Y值(第二个值);
5、interpolation:插值方式,可选的插值方式如下: 
       1)INTER_NEAREST:最近邻插值 ;
       2)INTER_LINEAR:双线性插值(默认值) ;
       3)INTER_CUBIC:双三次样条插值(逾4×4像素邻域内的双三次插值) ;
       4)INTER_LANCZOS4:Lanczos插值(逾8×8像素邻域的Lanczos插值) ;
6、borderMode,边界模式,有默认值BORDER_CONSTANT;
7、borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。

20.仿射变换:

(1)获取仿射变换矩阵:

(1)三点法计算仿射矩阵:

Mat getAffineTransform(const Point2f* src, const Point2f* dst)
【参数】:
1、src:原图的三个固定顶点;
2、dst:目标图像的三个固定顶点;
3、返回值:Mat型变换矩阵,可直接用于warpAffine()函数;
注意,顶点数组长度超过3个,则会自动以前3个为变换顶点;
      数组可用Point2f[]或Point2f*表示。


(2)指定比例和角度:
Mat getRotationMatrix2D (CvPoint2D32f  center,double angle,double scale)
【参数】:
1、center,表示源图像旋转中心;
2、参数double angle,旋转角度,正值表示逆时针旋转;
3、scale,缩放系数。

(2)执行仿射变换:

(1)仿射变换:
void warpAffine(InputArray src, OutputArray dst, InputArray M, Size dsize, int flags=INTER_LINEAR, int borderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())

【参数】:
1、src:输入变换前图像;
2、dst:输出图像,需要初始化一个空矩阵用来保存结果,不需要设定矩阵尺寸;
3、M:变换矩阵;
4、dsize:设置输出图像大小;
5、flags:设置插值方式,默认方式为线性插值;
6、borderMode:边界模式,默认值BORDER_CONSTANT;
7、borderValue:在恒定边界情况下取的值,默认值为Scalar(),即0。


(2)投影变换:
void warpPerspective (InputArray src, OutputArray dst, InputArray M, Size dsize, int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT, const Scalar &borderValue = Scalar(0))

【参数】:
1、src:输入图像;
2、dst:输出图像;
3、M:3x3变换矩阵;
4、dsize:输出图像的大小;
5、flags:插值方式;
6、borderMode:边界模式;
7、borderValue:在恒定边界情况下取的值,默认值为Scalar(),即0。

(3)平移变换:

         图像的平移也分为两步:首先定义好图像的平移矩阵,分别指定x方向和y方向上的平移量tx和ty,再根据平移矩阵执行仿射变换。

cv::Mat src = cv::imread("lenna.jpg");
cv::Mat dst;
cv::Size dst_sz = src.size();

//定义平移矩阵
cv::Mat t_mat =cv::Mat::zeros(2, 3, CV_32FC1);
t_mat.at<float>(0, 0) = 1;
t_mat.at<float>(0, 2) = 20; //水平平移量
t_mat.at<float>(1, 1) = 1;
t_mat.at<float>(1, 2) = 10; //竖直平移量

//根据平移矩阵进行仿射变换
cv::warpAffine(src, dst, t_mat, dst_sz);

//显示平移效果
cv::imshow("image", src);
cv::imshow("result", dst);

(4)旋转变换:

(1)顺时针旋转90度:
CV_EXPORTS_W void transpose(InputArray src, OutputArray dst);

(2)顺时针旋转90、180、270度:
CV_EXPORTS_W void rotate(InputArray src, OutputArray dst, int rotateCode);
【参数】:
1、src:输入mat;
2、dst:输出mat;
3、rotateCode:旋转枚举;
               ROTATE_90_CLOCKWISE(0),            //顺时针90度;
               ROTATE_180(1),                     //顺时针180度;
               ROTATE_90_COUNTERCLOCKWISE(2);    //逆时针90度,等于顺时针270度。

21.复制图像通道:

        https://blog.csdn.net/akadiao/article/details/79006929

        mixChannels()函数用于将输入数组的指定通道复制到输出数组的指定通道。  

(1)void mixChannels(const Mat* src, size_t nsrcs, Mat* dst, size_t ndsts, const int* fromTo, size_t npairs);
(2)void mixChannels(const vector<Mat>& src, vector<Mat>& dst, const int* fromTo, int npairs)


【参数】:
1、src:输入数组或向量矩阵,所有矩阵的大小和深度必须相同;
2、nsrcs:矩阵的数量;
3、dst:输出数组或矩阵向量,大小和深度必须与src[0]相同;
4、ndsts:矩阵的数量;
5、fromTo:指定被复制通道与要复制到的位置组成的索引对;
6、npairs:fromTo中索引对的数目。

22.直方图处理:

(1)计算直方图:

(1)void calcHist (const Mat* images,int nimages,const int* channels,InputArray mask, OutputArray hist,int dims, const int* histSize, const float** ranges,bool uniform = true, bool accumulate=false )
(2)void calcHist (const Mat* images,int nimages,const int* channels,InputArray mask, SparseMat& hist, int dims, const int* histSize, const float** ranges,bool uniform = true, bool accumulate=false) 
(3)void calcHist (InputArrayOfArrays images, const vector<int>& channels, InputArray    mask, OutputArray hist, const vector<int>& histSize, const vector<float>& ranges, bool accumulate=false)    

【参数】:
1、images:源图像数组,数组中的图像有同样的位深CV_8U或 CV_32F,同样的尺寸;其中的每一个图像都可以有任意多个通道;
2、nimages:源图像的数目;
3、channels:维度通道序列;
             第一幅图像的通道标号从0~image[0].channels( )-1,其中Image[0]表示图像数组中的第一幅图像,channels()表示该图像的通道数量;
             第二幅图像,通道标号从image[0].channerls( )~image[1].channels( )-1;
             其余图像的通道标号顺序依此类推,也就是说图像阵列中的所有图像的通道根据图像排列顺序,排成一个通道队列;
4、mask:可选择参数mask,在图像中只有被mask覆盖的区域的像素才参与直方图统计。如果这个参数想用默认值,可以输入Mat();如果参数不为空,那么它必须是一个8-bit的与images[i]同尺寸的矩阵;
5、hist:输出直方图, 它是一个稠密或稀疏矩阵,具有dims个维度;
6、dims:直方图的维度,当前OpenCV版本最大值为32;当参数dims>1时,输出矩阵Hist是二维矩阵;
7、histSize:数组,histSize[i]表示第i个维度上bin的个数,这里的维度可以理解为通道;
8、ranges:【1】当uniform=true时,即在每个维度(或通道)上每个直方条等宽时,ranges是多个二元数组组成的数组:
               1)灰度值的有效统计范围的下界用L0表示,上界用UhistSize[i]-1表示,角标中的i表示第i个维度(或通道),上下界值可以表示为hrange[i]={ L0, UhistSize[i]-1},在统计时L0和UhistSize[i]-1不在统计范围内。
               2)而ranges={ hrange[0], hrange[1], …… , hrange[dims]},ranges的元素个数由参数dims决定。在该维度上直方条的个数为histSize[i],如hrange[0]={ L0, UhistSize[0]},hrange[1]={ L1, UhistSize[1]}, hrange[2]={ L2, UhistSize[2]}, …… , hrange[dims]={ L0, UhistSize[0]}。
          【2】当uniform=false时,ranges是多元数组组成的数组,ranges中的每个元素ranges[i]都是一个多元数组,元素个数为histSize[i]+1,它们分别是:L0 , U0=L1, U1= L2, …… ,UhistSize[i]-2 , LhistSize[i]-1 , UhistSize[i]-1 。所以,ranges[i]={ L0 , L1, L2, …… , LhistSize[i]-1 ,UhistSize[i]-1} 
9、uniform:标识,用于说明直方条bin是否是均匀等宽;
10、accumulate:累积标识,如果该项设置则当直方图重新分配时直方图再开始清零。这个特征可以使通过几幅图像累积计算一个简单的直方图,或者及时更新直方图。

注:函数calcHist可以计算一幅或多幅图像的直方图,在元组中增量一个直方图的时候,就是从输入图像组中的原位置提取一幅图像,计算出它的直方图并添加到元组中。

(2)计算最值:

(1)void minMaxLoc(InputArray src, double* minVal, double* maxVal=0, Point* minLoc=0, Point* maxLoc=0, InputArray mask=noArray())
(2)void minMaxLoc(const SparseMat& src, double* minVal, double* maxVal, int* minIdx=0, int* maxIdx=0)

【参数】:
1、src:单通道源图像;
2、minVal:指向返回的最小值的指针,如果不需要则使用NULL;
3、maxVal:指向返回的最大值的指针,如果不需要则使用NULL;
4、minLoc:返回的最小位置的指针(在2D情况下), 如果不需要则使用NULL;
5、maxLoc:返回的最大位置的指针(在2D情况下),如果不需要则使用NULL;
6、mask:用于选择子数组的mask,只对源图像中mask范围内的部分进行处理。 
【注】minMaxLoc()函数存在两个版本,第一个版本最常用。

(3)直方图均衡化:

         直方图均衡化是通过拉伸像素强度分布范围来增强图像对比度的一种方法,均衡化指的是把一个分布 (给定的直方图) 映射 到另一个分布 (一个更宽更统一的强度值分布), 所以强度值分布会在整个范围内展开。

         直方图均衡化的计算流程为:1.计算输入图像的直方图H;2.进行直方图归一化,直方图的组距的和为255;3.计算直方图积分;4.以查询表形式进行图像变换。 

void equalizeHist(InputArray src, OutputArray dst)

【参数】:
1、src:8位单通道源图像; 
2、dst:结果图像,与输入图像具有相同的尺寸和类型。

(4)直方图对比:

         https://blog.csdn.net/u013162035/article/details/79429132

(1)double compareHist(InputArray H1,  InputArray H2,  int method)
(2)double compareHist(const SparseMat& H1, const SparseMat& H2, int method)

【参数】:
1、H1:第一个参与比较的直方图;
2、H2:第二个参与比较的直方图,与H1有相同的尺寸;
3、method:比较方式:
         1)CV_COMP_CORREL:Correlation 
         2)CV_COMP_CHISQR:Chi-Square(卡方)
         3)CV_COMP_INTERSECT:Intersection(直方图相交)
         4)CV_COMP_BHATTACHARYYA:Bhattacharyya distance(Bhattacharyya 距离)

(5)直方图反向投影:

         反向投影用于在输入图像(通常较大)中查找特定图像(通常较小或者仅1个像素,以下将其称为模板图像)最匹配的点或者区域,也就是定位模板图像出现在输入图像的位置。

         反向投影的查找的方式就是不断的在输入图像中切割跟模板图像大小一致的图像块,并用直方图对比的方式与模板图像进行比较。

         假设有一张100x100的输入图像,有一张10x10的模板图像,查找的过程是这样的:
         1)从输入图像的左上角(0,0)开始,切割一块(0,0)至(10,10)的临时图像;
         2)生成临时图像的直方图;
         3)用临时图像的直方图和模板图像的直方图对比,对比结果记为c;
         4)直方图对比结果c,就是结果图像(0,0)处的像素值;
         5)切割输入图像从(0,1)至(10,11)的临时图像,对比直方图,并记录到结果图像;
         6)重复(1)~(5)步直到输入图像的右下角。

         可以这样理解:对于calcBackProjectPatch(基于块的反向投影形式),利用直方图做类似于模板匹配的匹配工作,结果会是一张灰度图。如果输入图像和模板图像一样大,那么反向投影相当于直方图对比;如果输入图像比模板图像还小,无法进行反向投影。

(1)void calcBackProject(const Mat* arrays, int narrays, const int* channels, InputArray hist, OutputArray backProject, const float** ranges, double scale=1, bool uniform=true )
(2)void calcBackProject(const Mat* arrays, int narrays, const int* channels, const SparseMat& hist, OutputArray backProject, const float** ranges, double scale=1, bool uniform=true )

【参数】:
1、arrays:输入的图像(或图像集),它们需为相同深度(CV_8U 或 CV_32F)和相同尺寸,而通道数任意;
2、narrays:输入图像个数;
3、channels:需要统计图像的通道索引即第几个通道,第一幅图的通道索引可选范围 [0, images[0]. channels() - 1],第二幅图的通道索引可选范围 [images[0].channels(), images[0].channels() + images[1]. channels() - 1],以此类推; 
4、hist:输入的直方图;
5、backProject:反向投影图像,需为单通道,并且和 images[0] 有相同的大小和深度;
6、ranges:直方图中x轴的取值范围;
7、scale:缩放因子,backProject [i][j] = scale * hist [images[k] [i][j]],有默认值1;
8、uniform:用于说明直方条bin是否是均匀等宽的标识符,有默认值 true。

23.模板匹配:

        https://blog.csdn.net/u013162035/article/details/79450430

        模板匹配算法需要滑动模板图像和原图像进行比较,图像块一次移动一个像素 (从左往右,从上往下),在每一个位置,都进行一次度量来计算这块图像与模板图像的相似度,将度量值保存到结果图像矩阵中. 在结果矩阵中的每个位置(x,y)都表示此处的匹配度量值。

void matchTemplate( InputArray image, InputArray temp, OutputArray result, int method) 

【参数】:
1、image:待匹配的源图像;
2、templ:模板图像;
3、result:结果矩阵,可以通过minMaxLoc() 确定结果矩阵的最大值和最小值的位置;(minMaxLoc()函数:查找全局最小和最大稀疏数组元素并返回其值及其位置。)
4、method :模板匹配的算法,有以下六种:
             0)CV_TM_SQDIFF:平方差匹配,利用平方差来进行匹配,最好匹配为0,匹配越差,匹配值越大;
             1)CV_TM_SQDIFF_NORMED :标准平方差匹配,匹配数值越低表示匹配效果越好;
             2)CV_TM_CCORR:相关匹配,采用模板和图像间的乘法操作,所以较大的数表示匹配程度较高,0标识最坏的匹配效果;
             3)CV_TM_CCORR_NORMED :标准相关匹配;
             4)CV_TM_CCOEFF:相关匹配,将模版对其均值的相对值与图像对其均值的相关值进行匹配,1表示完美匹配,-1表示糟糕的匹配,0表示没有任何相关性(随机序列);
             5)CV_TM_CCOEFF_NORMED:标准相关匹配;

【注】:
1、TM_SQDIFF,TM_SQDIFF_NORMED匹配数值越低表示匹配效果越好,其它四种反之;
2、TM_SQDIFF_NORMED,TM_CCORR_NORMED,TM_CCOEFF_NORMED是标准化的匹配,得到的最大值/最小值范围在0~1之间,其它则需要自己对结果矩阵归一化(normalize())。
   不同的方法会得到差异很大的结果,可以通过测试选择最合适的方法。

24.轮廓的查找与绘制:

(1)轮廓查找:

          轮廓查找的理论基础为用来对二值图像进行拓扑分析的两种算法:

          1)在确定二值图像边界的围绕关系,即确定外边界、孔边界以及它们的层次关系时,由于这些边界和原图的区域具有一一对应关系(外边界对应像素值为1的连通区域,孔边界对应像素值为0的区域),因此可以用边界来表示原图;

           2)与算法1本质相同,但它只查找最外层的边界。 

findContours( InputOutputArray image,  OutputArrayOfArrays contours, OutputArray hierarchy,  int mode, int method, Point offset=Point());  

【参数】:
1、image:单通道图像矩阵,可以是灰度图,但更常用的是二值图像,一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;

2、contours:定义为“vector<vector<Point>> contours”,是一个双重向量(向量内每个元素保存了一组由连续的Point构成的点的集合的向量);
             每一组点集就是一个轮廓,有多少轮廓,contours就有多少元素;

3、hierarchy:hierarchy的定义为:vector<Vec4i> hierarchy;
             Vec4i的定义:typedef Vec<int, 4> Vec4i;(向量内每个元素都包含了4个int型变量),        
             从定义上看,hierarchy是一个向量,向量内每个元素都是一个包含4个int型的数组。向量hierarchy内的元素和轮廓向量contours内的元素是一一对应的,向量的容量相同。
             hierarchy内每个元素的4个int型变量是hierarchy[i][0] ~ hierarchy[i][3],分别表示当前轮廓i的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓的编号索引,如果当前轮廓没有对应的后一个轮廓、前一个轮廓、父轮廓和内嵌轮廓,则相应的hierarchy[i][*]被置为-1。

4、mode:定义轮廓的检索模式,取值如下:
         1)CV_RETR_EXTERNAL:只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略;
         2)CV_RETR_LIST:检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1;
         3)CV_RETR_CCOMP: 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层;
         4)CV_RETR_TREE: 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。

5、method:定义轮廓的近似方法,取值如下:
         1)CV_CHAIN_APPROX_NONE:保存物体边界上所有连续的轮廓点到contours向量内;
         2)CV_CHAIN_APPROX_SIMPLE:仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留;
         3)CV_CHAIN_APPROX_TC89_L1:使用teh-Chinl chain 近似算法;
         4)CV_CHAIN_APPROX_TC89_KCOS:使用teh-Chinl chain 近似算法。
6、Point偏移量,所有的轮廓信息相对于原始图像对应点的偏移量,相当于在每一个检测出的轮廓点上加上该偏移量,并且Point可以是负值。

(2)轮廓绘制:

void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )

【参数】:
1、image:目标图像,可为Mat的对象; 
2、contours:所有的输入轮廓,每一个轮廓都存储一个点向量,即point类型的vector表示;
3、contourIdx:指明绘制哪些轮廓,如果该参数为负值则绘制全部轮廓;
4、color:轮廓的颜色; 
5、thickness:轮廓的线宽,如果为负值或CV_FILLED表示填充轮廓内部; 
6、lineType:线型;
7、hierarchy:轮廓结构信息;
8、maxLevel:绘制轮廓的最大层级。
            如果为0,则只绘制指定的轮廓线;
            如果是1,函数绘制轮廓线和所有嵌套轮廓线;
            如果是2,函数绘制轮廓/所有嵌套的轮廓/所有嵌套到嵌套的轮廓,以此类推。
            只有在有层次结构可用时才考虑此参数;
9、offset:可选的轮廓位移参数,按指定方式移动所有绘制的轮廓线。 

【注】:OpenCV3在thickness的每个取值去掉了“CV_”。

【应用举例】:
void on_ThreshChange(int, void* ){
	// Canny算子检测边缘
	Canny( g_grayImage, g_cannyMat_output, g_nThresh, g_nThresh*2, 3 );
	// 寻找轮廓
	findContours( g_cannyMat_output, g_vContours, g_vHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
	// 绘制轮廓
	Mat drawing = Mat::zeros( g_cannyMat_output.size(), CV_8UC3 );
	for( int i = 0; i< g_vContours.size(); i++ )
	{
		Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );//任意值
		drawContours( drawing, g_vContours, i, color, 2, 8, g_vHierarchy, 0, Point() );
	}
	// 结果显示
	imshow( WINDOW_NAME2, drawing );
}

25.凸包查找:

       https://blog.csdn.net/u013162035/article/details/79490420

       常见的凸包查找方式有两种:Graham’s Scan法和Jarvis步进法。

       1)Graham’s Scan法:

             Graham扫描法通过不断在凸壳中加入新的点和去除影响凸性的点,最后形成凸包。算法的主体由两部分组成,先排序然后扫描。

             首先对点集排序,对杂乱的点集进行梳理,排序的方法有极角坐标排序(极角序)和直角坐标排序(水平序)两种方法。在实现的时候直角坐标排序比较方便。

             然后进行栈扫描,核心思想是按照排好的序一次加入新点得到的边,边的寻找符合左旋判定。如果和上一条边成左转关系就压栈继续;如果右转就出栈直到和栈顶两点的边成左转关系,压栈继续。

       2)Jarvis步进法:

             首先,查找到横坐标最小的点(如有一样则取相同点纵坐标更小的点);
             然后从这点开始,查找最靠近外侧的点(通过叉积比较);
             遍历所有点,直到重新找到起点后退出。

void convexHull(InputArray points, OutputArray hull, bool clockwise=false, bool returnPoints=true )

【参数】:
1、points:输入的二维点集,Mat类型数据即可; 
2、hull:输出参数,用于输出函数调用后找到的凸包;
3、clockwise:操作方向,当标识符为真时,输出凸包为顺时针方向,否则为逆时针方向;
4、returnPoints:操作标识符,默认值为true,此时返回各凸包的各个点;否则返回凸包各点的指数,当输出数组vector时,此标识被忽略。

【应用举例】:
void on_ThreshChange(int, void* ){
	// 对图像进行二值化,控制阈值
	threshold( g_grayImage, g_thresholdImage_output, g_nThresh, 255, THRESH_BINARY );
	// 寻找轮廓
	findContours( g_thresholdImage_output, g_vContours, g_vHierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
	// 遍历每个轮廓,寻找其凸包
	vector<vector<Point> >hull( g_vContours.size() );
	for( unsigned int i = 0; i < g_vContours.size(); i++ ){  
		convexHull( Mat(g_vContours[i]), hull[i], false );
	}
	// 绘出轮廓及其凸包
	Mat drawing = Mat::zeros( g_thresholdImage_output.size(), CV_8UC3 );
	for(unsigned  int i = 0; i< g_vContours.size(); i++ ){
		Scalar color = Scalar( g_rng.uniform(0, 255), g_rng.uniform(0,255), g_rng.uniform(0,255) );
		drawContours( drawing, g_vContours, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
		drawContours( drawing, hull, i, color, 1, 8, vector<Vec4i>(), 0, Point() );
	}
	// 显示结果
	imshow( WINDOW_NAME2, drawing );
}

26.轮廓形状转换:

(1)外接矩形:

(1)smallest_rectangle1:
Rect boundingRect(InputArray points)  
【参数】:
1、points:输入的二维点集。

(2)smallest_rectangle2:
RotatedRect minAreaRect(InputArray points)
【参数】:
1、points:输入的二维点集。

(2)外接圆:

void minEnclosingCircle(InputArray points, Point2f& center, float& radius)

【参数】:
1、points:输入的二维点集,数据类型为vector<>或Mat类型; 
2、center:最小外接圆的圆心坐标;
3、radius:最小外接圆的半径。

(3)拟合椭圆:

RotatedRect fitEllipse(InputArray points)

【参数】:
1、points:输入二维点集。

【应用举例】:
//在随机点中寻找拟合的椭圆  
RotatedRect ellipsemege = fitEllipse(points);
//根据得到的椭圆的信息  绘制椭圆  
ellipse(srcImage, ellipsemege, Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255)), 3);
//结果显示
imshow("椭圆包围实例", srcImage);

(4)逼近多边形:

void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)

【参数】 
1、curve:输入的二维点集,可以是vector类型或Mat类型 ; 
2、approxCurve:多边形逼近的结果,其类型与输入的点集类型一致; 
3、epsilon:逼近的精度,为原始曲线和逼近曲线间的最大值; 
4、closed:如果为true,逼近的曲线为封闭曲线,如果为false则逼近曲线不封闭。

(5)测试点是否在轮廓内:

          https://blog.csdn.net/kakiebu/article/details/81983714

double pointPolygonTest(InputArray contour, 
                        Point2f pt, 
                        bool measureDist);

【参数】 :
1、contour:输入的轮廓; 
2、pt:轮廓中检测的点; 
3、measureDist:当measureDist设置为true时,返回实际距离值:
                   a.若返回值为正,表示点在多边形内部;
                   b.返回值为负,表示在多边形外部;
                   c.返回值为0,表示在多边形上;
               当measureDist设置为false时,返回 -1、0、1三个固定值;
                   a.若返回值为+1,表示点在多边形内部;
                   b.返回值为-1,表示在多边形外部;
                   c.返回值为0,表示在多边形上。

27.图像的矩:

          https://blog.csdn.net/qq_37207090/article/details/83986950

          https://blog.csdn.net/Vichael_Chan/article/details/100881617

          从一幅图像计算出来的矩集,不仅可以描述图像形状的全局特征,而且可以提供大量关于该图像不同的几何特征信息,如大小,位置、方向和形状等。矩函数在图像分析中有着广泛的应用,如模式识别、目标分类、目标识别与方位估计、图像的编码与重构等。

(1)空间矩/中心矩/中心归一化矩计算:

         moments()函数计算多边形或栅格化形状(一个矢量形状或光栅形状)的最高达三阶的所有矩,结果在返回值结构Moments中返回。

Moments moments(InputArray array, bool binaryImage)	

【参数】:
1、array:光栅图像(单通道、8位或浮点二维数组)或二维点(点或点2f)的数组(1×N或N×1)
2、binaryImage:用来指示输出图像是否为一幅二值图像,如果是二值图像则图像中所有非0像素作为1进行计算。

【返回值】:
Moments::Moments	
(
// 空间矩(10个)
double 	m00,double 	m10,double 	m01,double 	m20,double 	m11,double 	m02,double 	m30,double 	m21,double 	m12,double 	m03  
// 中心矩(7个)
double mu20, double mu11, double mu02, double mu30, double mu21 , double mu12,double mu03
// 中心归一化矩(7个) 
double nu20, double nu11, double nu02, double nu30, double nu21, double nu12,double nu03;
)		

(2)Hu矩计算:

         根据二阶矩和三阶矩可以推导出七个不变矩-Hu不变矩,HuMoments()函数用于由中心矩计算Hu矩。

void HuMoments(const Moments& moments, double* hu)

【参数】:
1、moments:moments即为上面一个函数计算得到的moments类型;
2、hu:hu是一个含有7个数的数组。

28.轮廓面积/长度计算:

(1)面积计算:

double contourArea(InputArray contour, bool oriented=false )

【参数】:
1、contour:输入的二维点集(轮廓顶点),可以是vector或Mat类型;
2、orientation:面向区域标识符,有默认值false;
               若参数值为true,该函数返回一个带符号的面积值,正负取决于轮廓的方向顺时针还是逆时针;
               若参数值为false,表示以绝对值返回。

(2)轮廓计算:

double arcLength(InputArray curve, bool closed);

【参数】:
1、curve,输入的二维点集(轮廓点),可以是vector或Mat类型;
2、closed,用于指示曲线是否封闭。

29.图论分割:

     https://www.cnblogs.com/tornadomeet/archive/2012/11/09/2763271.html

     图论分割把图像分割问题与图的最小割问题相关联,GrubCut的基本方法是:将图像中用户指定的框外像素全部作为背景,而框内的像素设定为可能前景,通过背景元素和可能的前景元素分别训练前景和背景的混合高斯模型GMM的参数,然后通过这个的混合高斯模型GMM计算网络图中T-link,再根据邻域关系建立N-link,到此网络图构造结束;根据最小割-最大流的方法,求此GMM模型下的最佳分割;然后再用分割后的数据再次训练前景和背景的GMM参数,再次计算T-link并进行求割,如此迭代,因为每次迭代能量都是递减的,所以可以保证收敛,并得到最后的分割结果。

void grabCut( InputArray img, InputOutputArray mask, Rect rect, InputOutputArray bgdModel, InputOutputArray fgdModel,int iterCount, int mode = GC_EVAL );

【参数】:
1、img:待分割的源图像,必须是8位3通道(CV_8UC3)图像,在处理的过程中不会被修改; 
2、mask:掩码图像,如果使用掩码进行初始化,那么mask保存初始化掩码信息;在执行分割的时候,也可以将用户交互所设定的前景与背景保存到mask中,然后再传入grabCut函数;在处理结束之后,mask中会保存结果。   
         mask只能取以下四种值: 
         GCD_BGD(=0),背景; 
         GCD_FGD(=1),前景; 
         GCD_PR_BGD(=2),可能的背景; 
         GCD_PR_FGD(=3),可能的前景。 
         如果没有手工标记GCD_BGD或者GCD_FGD,那么结果只会有GCD_PR_BGD或GCD_PR_FGD; 
3、rect:用于限定需要进行分割的图像范围,只有该矩形窗口内的图像部分才被处理; 
4、bgdModel:背景模型,如果为null,函数内部会自动创建一个bgdModel,bgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5; 
5、fgdModel:前景模型,如果为null,函数内部会自动创建一个fgdModel,fgdModel必须是单通道浮点型(CV_32FC1)图像,且行数只能为1,列数只能为13x5; 
6、iterCount:迭代次数,必须大于0; 
7、mode:用于指示grabCut函数进行什么操作,可选的值有: 
         GC_INIT_WITH_RECT(=0),用矩形窗初始化GrabCut; 
         GC_INIT_WITH_MASK(=1),用掩码图像初始化GrabCut; 
         GC_EVAL(=2),执行分割。

【应用举例】:
//读入图像
Mat img = imread("1.jpg",1); 
Mat bgModel, fgModel, mask;
//指定矩形框
Rect rect;
rect.x = 20;
rect.y = 30;
rect.width = img.cols - (rect.x << 1);
rect.height = img.rows - (rect.y << 1);
//使用grabCut算法分割
grabCut(img, mask, rect, bgModel, fgModel, 3, GC_INIT_WITH_RECT);
compare(mask, GC_PR_FGD, mask, CMP_EQ);
Mat foreground(img.size(), CV_8UC3, Scalar(255, 255, 255));
img.copyTo(foreground, mask);
//结果显示
imshow("分割后的图像", foreground);

30.角点检测:

     角点的特点包括:   

     1)一阶导数(即灰度的梯度)的局部最大所对应的像素点;

     2)两条及两条以上边缘的交点;

     3)图像中梯度值和梯度方向的变化速率都很高的点;

     4)角点处的一阶导数最大,二阶导数为零,指示物体边缘变化不连续的方向。

     在当前的图像处理领域,角点检测算法可归纳为三类:

     1)基于灰度图像的角点检测:基于灰度图像的角点检测又可分为基于梯度、基于模板和基于模板梯度组合三类方法,常见的基于模板的角点检测算法包括Kitchen-Rosenfeld角点检测算法、Harris角点检测算法、KLT角点检测算法及SUSAN角点检测算法。

     2)基于二值图像的角点检测;

     3)基于轮廓曲线的角点检测。

(1)Harris角点检测:

         http://www.360doc.com/content/15/1114/16/25664332_513168246.shtml

//Harris角点检测:
void cornerHarris( InputArray src,OutputArray dst, int blockSize, int ksize, double k, intborderType=BORDER_DEFAULT )  

【参数】:
1、src:输入图像,可为Mat类的对象,且需为单通道8位或者浮点型图像; 
2、dst:这个参数用于存放Harris角点检测的输出结果,和源图片有一样的尺寸和类型;
3、blockSize:邻域的大小;
4、ksize:表示Sobel()算子的孔径大小;
5、k:Harris参数;
6、borderType:边界模式。

【应用举例】:
//角点检测
cornerHarris(g_grayImage, dstImage, 2, 3, 0.04, BORDER_DEFAULT);
//归一化
normalize(dstImage, normImage, 0, 255, NORM_MINMAX, CV_32FC1, Mat());
//转换:将归一化后的图线性变换成8位无符号整型
convertScaleAbs( normImage, scaledImage); 
//绘制角点,将检测到的,且符合阈值条件的角点绘制出来
for( int j = 0; j < normImage.rows ; j++)
   { for( int i = 0; i < normImage.cols; i++)
	{
	     if( (int) normImage.at<float>(j,i) > thresh+80 )
	     {
		circle( g_srcImage1, Point( i, j ), 5,  Scalar(10,10,255), 2, 8, 0 );
		circle( scaledImage, Point( i, j ), 5,  Scalar(0,10,255), 2, 8, 0 );
	     }
	}
    }
//显示结果
imshow( WINDOW_NAME2, scaledImage );

(2)Shi-Tomasi角点检测:

void goodFeaturesToTrack( InputArray image, OutputArray corners, int maxCorners, double qualityLevel, double minDistance, InputArray mask=noArray(), int blockSize=3, bool useHarrisDetector=false, double k=0.04 )

【参数】:
1、image:输入图像(8位或32位单通道图);
2、corners:检测到的所有角点,类型为vector或数组,由实际给定的参数类型而定;
           如果是vector,那么它应该是一个包含cv::Point2f的vector对象;
           如果类型是cv::Mat,那么它的每一行对应一个角点,点的x、y位置分别是两列。
3、maxCorners:用于限定检测到的点数的最大值;
4、qualityLevel:表示检测到的角点的质量水平(通常是0.10到0.01之间的数值,不能大于1.0);
5、minDistance:用于区分相邻两个角点的最小距离,小于这个距离得点将进行合并;
6、mask:如果指定它的维度必须和输入图像一致,且在mask值为0处不进行角点检测;
7、blockSize:表示在计算角点时参与运算的区域大小,常用值为3,但是如果图像的分辨率较高则可以考虑使用较大一点的值;
8、useHarrisDetector:用于指定角点检测的方法,如果是true则使用Harris角点检测,false则使用Shi Tomasi算法;
9、k:是在使用Harris算法时使用,最好使用默认值0.04。

【应用举例】:
//使用灰度图像进行角点检测
Mat image_gray;
cvtColor(image_color, image_gray, COLOR_BGR2GRAY);
//设置角点检测参数
vector<Point2f> corners;
int max_corners = 200;
double quality_level = 0.01;
double min_distance = 3.0;
int block_size = 3;
bool use_harris = false;
double k = 0.04;
//角点检测
goodFeaturesToTrack(image_gray, corners, max_corners, quality_level, min_distance, Mat(), block_size, use_harris, k);
//绘制角点
for (int i = 0; i < corners.size(); i++){
     circle(image_color, corners[i], 1, Scalar(0, 0, 255), 2, 8, 0);
}
//结果显示
imshow("house corner", image_color);

(3)亚像素角点检测:

          可以通过调用亚像素角点检测函数将Harris等角点检测算法提取出的像素级的角点坐标精确到亚像素级别。

 void cornerSubPix( InputArray image,  InputOutputArray corners,  Size winSize,  Size zeroZone, TermCriteria criteria)

【参数】:
1、image:输入图像,与goodFeaturesToTrack()中的输入图像相同;
2、corners:检测到的角点,既是输入角点的初始坐标,也是输出的精确坐标;
3、winSize:计算亚像素角点时考虑的区域的大小,大小为NXN; N=(winSize*2+1);
4、zeroZone:作用类似于winSize,但是总是具有较小的范围,通常忽略(即Size(-1, -1));
5、criteria:用于表示计算亚像素时停止迭代的标准,可选参数值有TermCriteria::MAX_ITER 、TermCriteria::EPS(可以是两者其一,也可以两者均选);
            1)TermCriteria::MAX_ITER:表示迭代次数达到了最大次数时停止;
            2)TermCriteria::EPS:表示角点位置变化的最小值已经达到最小时停止迭代。二者均使用cv::TermCriteria()构造函数进行指定。

【应用举例】:
//(1)调用Shi-Tomasi算法(goodFeaturesToTrack函数)
vector<Point2f> corners;
double qualityLevel = 0.01;
double minDistance = 10;
int blockSize = 3;
double k = 0.04;
Mat copy = g_srcImage.clone();	
goodFeaturesToTrack( g_grayImage, corners, g_maxCornerNumber, qualityLevel, minDistance, Mat(), blockSize, false, k);

//(2)亚像素角点检测的参数设置
Size winSize = Size( 5, 5 );
Size zeroZone = Size( -1, -1 );
TermCriteria criteria = TermCriteria( CV_TERMCRIT_EPS + CV_TERMCRIT_ITER, 40, 0.001 );

//(3)计算出亚像素角点位置
cornerSubPix( g_grayImage, corners, winSize, zeroZone, criteria );

//(4)输出角点信息
for( int i = 0; i < corners.size(); i++ ) {
      cout<<corners[i].x<<corners[i].y<<endl;
 }

(4)自定义角点检测:

         通过自定义操作可以使用cornerEigenValsAndVecs()函数和minMaxLoc()函数结合来模拟Harris角点检测,或者使用cornerMinEigenVal()函数和minMaxLoc()函数结合来模拟Shi-Tomasi角点检测,最后特征点选取的判断条件要根据实际情况进行选择。           

//(1)
void cornerEigenValsAndVecs(InputArray src, OutputArray dst, int blockSize, int ksize, int borderType=BORDER_DEFAULT );  

【参数】:
1、src:输入单通道8-bit或者浮点类型图像; 
2、dst:用来存储结果的图像,大小与输入图像一致并且为CV_32FC6类型(通道数必须比输入图像宽6倍),存储的是图像块的特征值和特征向量; 
3、blockSize:邻域大小;
4、ksize:Sobel算子当中的核大小,只能取1、3、5、7;
5、borderType:边界模式。

【应用举例】:
//载入图像
src = imread("1.jpg", 1);
cvtColor(src, src_gray, CV_BGR2GRAY);
//设置参数  
int blockSize = 3; int apertureSize = 3;
//计算图像块的特征值和特征向量,用于角点检测
myHarris_dst = Mat::zeros(src_gray.size(), CV_32FC(6));
Mc = Mat::zeros(src_gray.size(), CV_32FC1);
cornerEigenValsAndVecs(src_gray, myHarris_dst, blockSize, apertureSize, BORDER_DEFAULT);
//角点选择  
for (int j = 0; j < src_gray.rows; j++){
    for (int i = 0; i < src_gray.cols; i++){		
	// 两个特征值  
	float* lambda = myHarris_dst.ptr<float>(j, i);
	float lambda1 = lambda[0];
	float lambda2 = lambda[1];
	Mc.at<float>(j, i) = lambda1*lambda2 - 0.04*pow((lambda1 + lambda2), 2);
	}
}
minMaxLoc(Mc, &myHarris_minVal, &myHarris_maxVal, 0, 0, Mat());



//(2)
void cornerMinEigenVal(InputArray src, OutputArray dst, int blockSize, int ksize=3, int borderType=BORDER_DEFAULT );

【参数】:
1、src:输入单通道8-bit或者浮点类型图像; 
2、dst:用来存储结果的图像,必须为CV_32FC1类型,存储的是梯度矩阵的最小特征值; 
3、blockSize:邻域大小;
4、ksize:Sobel算子当中的核大小,只能取1、3、5、7;
5、borderType:边界模式。

【应用举例】:
myShiTomasi_dst = Mat::zeros(src_gray.size(), CV_32FC1);
cornerMinEigenVal(src_gray, myShiTomasi_dst, blockSize, apertureSize, BORDER_DEFAULT);
minMaxLoc(myShiTomasi_dst, &myShiTomasi_minVal, &myShiTomasi_maxVal, 0, 0, Mat());

31.自适应滤波器:

(1)自适应流行滤波器实现:

Ptr<AdaptiveManifoldFilter> createAMFilter(double sigma_s, double sigma_r, bool adjust_outliers = false);

【参数】:
1、sigma_s:空间标准差,范围必须大于0;
2、sigma_r:颜色空间标准差,它类似于sigma在颜色空间中双边过滤器,范围必须大于0小于1;
3、adjust_outliers:调整异常值可选,指定是否使用随机数生成器计算特征向量。

(2)滤波函数:

void filter(InputArray src, OutputArray dst, InputArray joint = noArray());

【参数】:
1、src:输入图像,可为mat类型;
2、dst:输出图像,可为mat类型,与输入的尺寸通道相同;
3、joint :输入联结图。

【应用举例】:
// (1)使用自适应流形应用高维滤波。
Ptr<AdaptiveManifoldFilter> pAdaptiveManifoldFilter = createAMFilter (sigmaS/100.0f, sigmaR/100.0f, true);
pAdaptiveManifoldFilter->filter(srcMat, dstMat);
// copy到左下
mat = windowMat(Range(srcMat.rows, srcMat.rows * 2),
Range(srcMat.cols * 0, srcMat.cols * 1));
addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

// (2)使用自适应流形应用高维滤波。
Ptr<AdaptiveManifoldFilter> pAdaptiveManifoldFilter = createAMFilter(sigmaS/100.0f, sigmaR/100.0f, false);
pAdaptiveManifoldFilter->filter(srcMat, dstMat);
// copy到左下
mat = windowMat(Range(srcMat.rows, srcMat.rows * 2),
Range(srcMat.cols * 1, srcMat.cols * 2));
addWeighted(mat, 0.0f, dstMat, 1.0f, 0.0f, mat);

32.透视变换:

      透视变换是指利用透视中心、像点、目标点三点共线的条件,按透视旋转定律使透视面绕透视轴旋转某一角度,破坏原有的投影光线束,仍能保持承影面上投影几何图形不变的变换,是将成像投影到一个新的视平面,也被称作投影映射。

(1)四点获取透视矩阵:
Mat getPerspectiveTransform( InputArray src, InputArray dst );

【参数】:
1、src:InputArray类型的src,输入4个点,std::vector<cv::Point2f>;
2、dst :InputArray类型的dst,输入4个点。


(2)执行透视变换函数:
void warpPerspective( InputArray src,OutputArray dst,InputArray M,Size dsize,int flags = INTER_LINEAR, int borderMode = BORDER_CONSTANT,const Scalar& borderValue = Scalar());

【参数】:
1、src:InputArray类型的src,输入图像;
2、dst:OutputArray类型的dst,输出图像,大小与类型与输入图像一致;
3、M:InpuArray类型的M,3x3的变换矩阵;
4、dsize:Size类型的dsize,输出图像的尺寸;
5、flags :int类型的flags,线性插值方式:
           0:最近邻插值;
           1:双线性插值(默认值);
           2:三次样条插值;
           3:区域插值;
           4:Lanczos插值;
           5:位精确双线性插值;
           6:插值码掩码...
6、borderMode :边界模式;
7、borderValue :边界填充颜色。

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值