15基于opencv的旋转_仿射变换_SURF特征点检测

旋转、仿射变换和SURF特征点检测

一、弯曲变换函数warpAffine ()

1.1 warpAffine ()各参数详解

voidwarpAffine(InputArray src,OutputArray dst,InputArray M,Size dsize, int flags =INTER_LINEAR, intborderMode =BORDER_CONSTANT,constScalar& borderValue =Scalar())

Ø  第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可。

Ø  第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,需和源图片有一样的尺寸和类型。

Ø  第三个参数,InputArray类型的M,2×3的变换矩阵。

Ø  第四个参数,Size类型的dsize,表示输出图像的尺寸。

Ø  第五个参数,int类型的flags,插值方法的标识符。此参数有默认值INTER_LINEAR(线性插值),可选的插值方式如下:

INTER_NEAREST - 最近邻插值

INTER_LINEAR - 线性插值(默认值)

INTER_AREA - 区域插值

INTER_CUBIC –三次样条插值

INTER_LANCZOS4-Lanczos插值

CV_WARP_FILL_OUTLIERS- 填充所有输出图像的象素。如果部分象素落在输入图像的边界外,那么它们的值设定为 fillval.

CV_WARP_INVERSE_MAP –表示M为输出图像到输入图像的反变换,即 。因此可以直接用来做象素插值。否则,warpAffine函数从M矩阵得到反变换。

Ø  第六个参数,int类型的borderMode,边界像素模式,默认值为BORDER_CONSTANT。

Ø  第七个参数,const Scalar&类型的borderValue,在恒定的边界情况下取的值,默认值为Scalar(),即0。

 

另外提一点,我们的WarpAffine函数与一个叫做cvGetQuadrangleSubPix( )的函数类似,但是不完全相同。WarpAffine要求输入和输出图像具有同样的数据类型,有更大的资源开销(因此对小图像不太合适)而且输出图像的部分可以保留不变。而cvGetQuadrangleSubPix 可以精确地从8位图像中提取四边形到浮点数缓存区中,具有比较小的系统开销,而且总是全部改变输出图像的内容。

1.2调用示例 

 

二、旋转变换函数

2.1 getRotationMatrix2D()各参数详解

MatgetRotationMatrix2D(Point2fcenter,double angle,double scale)

Ø  第一个参数,Point2f类型的center,表示源图像的旋转中心。

Ø  第二个参数,double类型的angle,旋转角度。角度为正值表示向逆时针旋转(坐标原点是左上角)。

Ø  第三个参数,double类型的scale,缩放系数。

 

此函数计算以下矩阵:

 

其中:

 

2.2调用示例

 

三、 SURF特征点检测

在OpenCV中,使用SURF进行特征点描述主要是drawMatches方法和BruteForceMatcher类的运用。

3.1 drawMatches()函数各参数详解

drawMatches()函数用于绘制出相匹配的两个图像的关键点

voiddrawMatches(constMat& img1, constvector<KeyPoint>&keypoints1,constMat& img2, constvector<KeyPoint>&keypoints2, constvector<DMatch>& matches1to2,Mat&outImg,constScalar&matchColor =Scalar::all(-1),constScalar&singlePointColor =Scalar::all(-1),constvector<char>&matchesMask =vector<char>(),intflags = DrawMatchesFlags::DEFAULT)

 

voiddrawMatches(constMat& img1, constvector<KeyPoint>&keypoints1,constMat& img2, constvector<KeyPoint>&keypoints2,constvector<vector<DMatch>>&matches1to2,Mat&outImg,constScalar&matchColor =Scalar::all(-1),constScalar&singlePointColor =Scalar::all(-1),constvector<vector<char>>& matchesMask =vector<vector<char>>(), intflags = DrawMatchesFlags::DEFAULT)

 

除了第五个参数matches1to2和第九个参数matchesMask有细微的差别以外,两个版本的基本上相同。

Ø  第一个参数,const Mat&类型的img1,第一幅源图像。

Ø  第二个参数,const vector&类型的keypoints1,根据第一幅源图像得到的特征点,它是一个输出参数。

Ø  第三个参数,const Mat&类型的img2,第二幅源图像。

Ø  第四个参数,const vector&类型的keypoints2,根据第二幅源图像得到的特征点,它是一个输出参数。

Ø  第五个参数,matches1to2,第一幅图像到第二幅图像的匹配点,即表示每一个图1中的特征点都在图2中有一一对应的点、

Ø  第六个参数,Mat&类型的outImg,输出图像,其内容取决于第五个参数标识符falgs。

Ø  第七个参数,const Scalar&类型的matchColor,匹配的输出颜色,即线和关键点的颜色。它有默认值Scalar::all(-1),表示颜色是随机生成的。

Ø  第八个参数,const Scalar&类型的singlePointColor,单一特征点的颜色,它也有表示随机生成颜色的默认值Scalar::all(-1)。

Ø  第九个参数,matchesMask,确定哪些匹配是会绘制出来的掩膜,如果掩膜为空,表示所有匹配都进行绘制。

Ø  第十个参数,int类型的flags,特征绘制的标识符,有默认值DrawMatchesFlags::DEFAULT。可以在如下这个DrawMatchesFlags结构体中选取值:

struct DrawMatchesFlags

{

   enum

   {

      DEFAULT = 0, //Output image matrix will be created (Mat::create), 

      // i.e. existing memory ofoutput image may bereused. 

      // Two source images,matches, and singlekeypoints 

      // will be drawn. 

      // For each keypoint, only the center pointwillbe 

      // drawn (without a circlearound the keypoint withthe 

      // keypoint size andorientation). 

      DRAW_OVER_OUTIMG = 1, //Output image matrix will not be 

      // created (usingMat::create). Matches will bedrawn 

      // on existing contentof output image. 

      NOT_DRAW_SINGLE_POINTS = 2, //Single keypoints will not be drawn. 

      DRAW_RICH_KEYPOINTS = 4 // Foreach keypoint, the circle around 

      // keypoint withkeypoint size and orientationwill 

      // be drawn. 

   };

};

 

四、BruteForceMatcher类

完整程序核心算法:

Ø  使用 DescriptorExtractor 接口来寻找关键点对应的特征向量

Ø  使用 SurfDescriptorExtractor 以及它的函数 compute 来完成特定的计算

Ø  使用 BruteForceMatcher 来匹配特征向量

Ø 使用函数 drawMatches 来绘制检测到的匹配点

 

4.1 BruteForceMatcher类详解

template<classDistance>

class CV_EXPORTS BruteForceMatcher : publicBFMatcher

{

public:

   BruteForceMatcher(Distanced = Distance()) : BFMatcher(Distance::normType, false) { (void)d; }

   virtual~BruteForceMatcher() {}

};

 

五、完整程序(仿射变换)

// ********************仿射变换程序**************************

// ********************仿射变换程序**************************

#include "opencv2/highgui/highgui.hpp" 

#include "opencv2/imgproc/imgproc.hpp" 

#include  

 

//-----------------------------------【命名空间声明部分】-------------------------------------- 

//      描述:包含程序所使用的命名空间 

//----------------------------------------------------------------------------------------------- 

using namespacecv;

using namespacestd;

 

//-----------------------------------【宏定义部分】--------------------------------------------  

//      描述:定义一些辅助宏  

//------------------------------------------------------------------------------------------------  

#define WINDOW_NAME1"【原始图窗口】"                 //为窗口标题定义的宏  

#define WINDOW_NAME2"【经过Warp后的图像】"       //为窗口标题定义的宏  

#define WINDOW_NAME3"【经过WarpRotate后的图像】"       //为窗口标题定义的宏  

 

 

//-----------------------------------【全局函数声明部分】-------------------------------------- 

//      描述:全局函数的声明 

//----------------------------------------------------------------------------------------------- 

static void ShowHelpText();

 

 

//-----------------------------------main( )函数】-------------------------------------------- 

//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行 

//----------------------------------------------------------------------------------------------- 

int main()

{

   //0】改变console字体颜色 

   system("color 1A");

 

   //0】显示欢迎和帮助文字 

   ShowHelpText();

 

   //1】参数准备 

   //定义两组点,代表两个三角形 

   Point2f srcTriangle[3];

   Point2f dstTriangle[3];

   //定义一些Mat变量 

   Mat rotMat(2, 3, CV_32FC1);

   Mat warpMat(2, 3, CV_32FC1);

   Mat srcImage, dstImage_warp, dstImage_warp_rotate;

 

   //2】加载源图像并作一些初始化 

   srcImage = imread("E:\\1TJQ\\Opencv\\Images\\image1.jpg", 1);

   if(!srcImage.data) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~ \n"); return false; }

   // 设置目标图像的大小和类型与源图像一致 

   dstImage_warp = Mat::zeros(srcImage.rows, srcImage.cols, srcImage.type());

 

   //3】设置源图像和目标图像上的三组点以计算仿射变换 

   srcTriangle[0] = Point2f(0, 0);

   srcTriangle[1] = Point2f(static_cast<float>(srcImage.cols - 1), 0);

   srcTriangle[2] = Point2f(0, static_cast<float>(srcImage.rows - 1));

 

   dstTriangle[0] = Point2f(static_cast<float>(srcImage.cols*0.0),static_cast<float>(srcImage.rows*0.33));

   dstTriangle[1] = Point2f(static_cast<float>(srcImage.cols*0.65),static_cast<float>(srcImage.rows*0.35));

   dstTriangle[2] = Point2f(static_cast<float>(srcImage.cols*0.15),static_cast<float>(srcImage.rows*0.6));

 

   //4】求得仿射变换 

   warpMat =getAffineTransform(srcTriangle, dstTriangle);

 

   //5】对源图像应用刚刚求得的仿射变换 

   warpAffine(srcImage,dstImage_warp, warpMat, dstImage_warp.size());

 

   //6】对图像进行缩放后再旋转 

   // 计算绕图像中点顺时针旋转50度缩放因子为0.6的旋转矩阵 

   Point center = Point(dstImage_warp.cols / 2, dstImage_warp.rows / 2);

   double angle =-30.0;

   double scale =0.8;

   // 通过上面的旋转细节信息求得旋转矩阵 

   rotMat =getRotationMatrix2D(center, angle, scale);

   // 旋转已缩放后的图像 

   warpAffine(dstImage_warp,dstImage_warp_rotate, rotMat, dstImage_warp.size());

 

 

   //7】显示结果 

   imshow(WINDOW_NAME1, srcImage);

   imshow(WINDOW_NAME2, dstImage_warp);

   imshow(WINDOW_NAME3, dstImage_warp_rotate);

 

   // 等待用户按任意按键退出程序 

   waitKey(0);

 

   return 0;

}

 

 

//-----------------------------------ShowHelpText( )函数】----------------------------------   

//      描述:输出一些帮助信息   

//----------------------------------------------------------------------------------------------   

static void ShowHelpText()

{

   //输出一些帮助信息   

   printf("\n\n\n\t欢迎来到【仿射变换】示例程序~\n\n");

   printf("\t当前使用的OpenCV版本为 OpenCV "CV_VERSION);

   printf("\n\n\t\t\t\t\t\t\t\t by浅墨\n\n\n"

      );

}

 

六、完整程序(SURF特征点检测)

#include "opencv2/core/core.hpp" 

#include "opencv2/features2d/features2d.hpp" 

#include "opencv2/highgui/highgui.hpp" 

#include  

#include 

#include  

 

 

//-----------------------------------【命名空间声明部分】-------------------------------------- 

//      描述:包含程序所使用的命名空间 

//----------------------------------------------------------------------------------------------- 

using namespacecv;

using namespacestd;

 

//-----------------------------------【全局函数声明部分】-------------------------------------- 

//      描述:全局函数的声明 

//----------------------------------------------------------------------------------------------- 

static voidShowHelpText();//输出帮助文字 

 

 

//-----------------------------------main( )函数】-------------------------------------------- 

//      描述:控制台应用程序的入口函数,我们的程序从这里开始执行 

//----------------------------------------------------------------------------------------------- 

int main()

{

   //0】改变console字体颜色 

   system("color 1A");

 

   //0】显示欢迎和帮助文字 

   ShowHelpText();

 

   //1】载入素材图 

   Mat srcImage1 = imread("1.jpg",1);

   Mat srcImage2 = imread("2.jpg",1);

   if(!srcImage1.data || !srcImage2.data)

   {

      printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~\n");returnfalse;

   }

 

   //2】使用SURF算子检测关键点 

   intminHessian = 700;//SURF算法中的hessian阈值 

   SurfFeatureDetectordetector(minHessian);//定义一个SurfFeatureDetectorSURF特征检测类对象   

   std::vector<KeyPoint> keyPoint1, keyPoints2;//vector模板类,存放任意类型的动态数组 

 

   //3】调用detect函数检测出SURF特征关键点,保存在vector容器中 

   detector.detect(srcImage1,keyPoint1);

   detector.detect(srcImage2,keyPoints2);

 

   //4】计算描述符(特征向量) 

   SurfDescriptorExtractorextractor;

   Mat descriptors1, descriptors2;

   extractor.compute(srcImage1,keyPoint1, descriptors1);

   extractor.compute(srcImage2,keyPoints2, descriptors2);

 

   //5】使用BruteForce进行匹配 

   // 实例化一个匹配器 

   BruteForceMatcher<L2<float> > matcher;

   std::vector< DMatch > matches;

   //匹配两幅图中的描述子(descriptors 

   matcher.match(descriptors1,descriptors2, matches);

 

   //6】绘制从两个图像中匹配出的关键点 

   Mat imgMatches;

   drawMatches(srcImage1,keyPoint1, srcImage2, keyPoints2, matches, imgMatches);//进行绘制 

 

   //7】显示效果图 

   imshow("匹配图", imgMatches);

 

   waitKey(0);

   return 0;

}

 

//-----------------------------------ShowHelpText( )函数】----------------------------------   

//      描述:输出一些帮助信息   

//----------------------------------------------------------------------------------------------   

static voidShowHelpText()

{

   //输出一些帮助信息   

   printf("\n\n\n\t欢迎来到【SURF特征描述】示例程序~\n\n");

   printf("\t当前使用的OpenCV版本为 OpenCV "CV_VERSION

      "\n\n\t\t\t\t\t\t\t\t by浅墨\n\n\n");

}

 

参考内容:

http://www.cnblogs.com/mq0036/p/5902104.html

你可能感兴趣的:(opencv基础知识)