【OpenCV入门教程之十七】OpenCV重映射 SURF特征点检测合辑

本文介绍了OpenCV中的重映射概念,通过remap()函数进行图像变换,并详细解析了函数参数。同时,文章探讨了SURF特征点检测,包括算法概览和OpenCV中的实现。提供了详细的示例代码,帮助读者理解并应用这两个技术。
摘要由CSDN通过智能技术生成

分享一下我老师大神的人工智能教程!零基础,通俗易懂!http://blog.csdn.net/jiangjunshow

也欢迎大家转载本篇文章。分享知识,造福人民,实现我们中华民族伟大复兴!

               


 本系列文章由@浅墨_毛星云 出品,转载请注明出处。  

 文章链接: http://blog.csdn.net/poem_qianmo/article/details/30974513

 作者:毛星云(浅墨)    微博:http://weibo.com/u/1723155442

 知乎:http://www.zhihu.com/people/mao-xing-yun

 邮箱: happylifemxy@163.com

  写作当前博文时配套使用的OpenCV版本:  2.4.9

本篇文章中,我们一起探讨了OpenCV中重映射和SURF特征点检测相关的知识点,主要一起了解OpenCV中重映射相关的函数remap,SURF算法在OpenCV中的体现与应用。此博文一共有三个配套的麻雀虽小但五脏俱全的示例程序,其经过浅墨详细注释过的代码都在文中贴出,且文章最后提供了综合示例程序的下载。

 

依然是先看看程序运行截图。

重映射:

  

SURF特征点检测:

  

 






一、OpenCV重映射

 



1.1 重映射的概念简析

 

重映射,就是把一幅图像中某位置的像素放置到另一个图片指定位置的过程。为了完成映射过程, 我们需要获得一些插值为非整数像素的坐标,因为源图像与目标图像的像素坐标不是一一对应的。一般情况下,我们通过重映射来表达每个像素的位置 (x,y),像这样 :


g(x,y) = f ( h(x,y) )

 

在这里, g( ) 是目标图像, f() 是源图像, 而h(x,y) 是作用于 (x,y) 的映射方法函数。

 

来看个例子。 若有一幅图像 I ,想满足下面的条件作重映射:

 

h(x,y) = (I.cols - x, y )

 

这样的话,图像会按照 x 轴方向发生翻转。那么,源图像和效果图分别如下:

  


在OpenCV中,我们用函数remap( )来实现简单重映射,下面我们就一起来看看这个函数。

 

 



1.2 remap( )函数解析

 


remap( )函数会根据我们指定的映射形式,将源图像进行重映射几何变换,基于的式子如下:


 


需要注意,此函数不支持就地(in-place)操作。看看其原型和参数。


C++: void remap(InputArray src, OutputArraydst, InputArray map1, InputArray map2, int interpolation, intborderMode=BORDER_CONSTANT, const Scalar& borderValue=Scalar())


    • 第一个参数,InputArray类型的src,输入图像,即源图像,填Mat类的对象即可,且需为单通道8位或者浮点型图像。
    • 第二个参数,OutputArray类型的dst,函数调用后的运算结果存在这里,即这个参数用于存放函数调用后的输出结果,需和源图片有一样的尺寸和类型。
    • 第三个参数,InputArray类型的map1,它有两种可能的表示对象。
  • 表示点(x,y)的第一个映射。
  • 表示CV_16SC2 , CV_32FC1 或CV_32FC2类型的X值。
    • 第四个参数,InputArray类型的map2,同样,它也有两种可能的表示对象,而且他是根据map1来确定表示那种对象。
  • 若map1表示点(x,y)时。这个参数不代表任何值。
  • 表示CV_16UC1 , CV_32FC1类型的Y值(第二个值)。

  • 第五个参数,int类型的interpolation,插值方式,之前的resize( )函数中有讲到,需要注意,resize( )函数中提到的INTER_AREA插值方式在这里是不支持的,所以可选的插值方式如下:
      • INTER_NEAREST - 最近邻插值
      • INTER_LINEAR – 双线性插值(默认值)
      • INTER_CUBIC – 双三次样条插值(逾4×4像素邻域内的双三次插值)
      • INTER_LANCZOS4 -Lanczos插值(逾8×8像素邻域的Lanczos插值)

  • 第六个参数,int类型的borderMode,边界模式,有默认值BORDER_CONSTANT,表示目标图像中“离群点(outliers)”的像素值不会被此函数修改。
  • 第七个参数,const Scalar&类型的borderValue,当有常数边界时使用的值,其有默认值Scalar( ),即默认值为0。





1.3 详细注释的重映射示例程序



下面放出精简后的以remap函数为核心的示例程序,方便大家快速掌握remap函数的使用方法。

//-----------------------------------【程序说明】----------------------------------------------//  程序名称::《【OpenCV入门教程之十七】OpenCV重映射 & SURF特征点检测合辑 》 博文配套源码 //  开发所用IDE版本:Visual Studio 2010//    开发所用OpenCV版本: 2.4.9//  2014年5月26日 Created by 浅墨//  配套博文链接: http://blog.csdn.net/poem_qianmo/article/details/26977557//  PS:程序结合配合博文学习效果更佳//  浅墨的微博:@浅墨_毛星云 http://weibo.com/1723155442//  浅墨的知乎:http://www.zhihu.com/people/mao-xing-yun//  浅墨的豆瓣:http://www.douban.com/people/53426472///----------------------------------------------------------------------------------------------//-----------------------------------【头文件包含部分】---------------------------------------//  描述:包含程序所依赖的头文件//---------------------------------------------------------------------------------------------- #include "opencv2/highgui/highgui.hpp"#include "opencv2/imgproc/imgproc.hpp"#include <iostream>//-----------------------------------【命名空间声明部分】--------------------------------------//          描述:包含程序所使用的命名空间//-----------------------------------------------------------------------------------------------using namespace cv;//-----------------------------------【main( )函数】--------------------------------------------//          描述:控制台应用程序的入口函数,我们的程序从这里开始执行//-----------------------------------------------------------------------------------------------int main(  )//【0】变量定义 Mat srcImage, dstImage; Mat map_x, map_y; //【1】载入原始图 srcImage = imread( "1.jpg", 1 ); if(!srcImage.data ) { printf("读取图片错误,请确定目录下是否有imread函数指定的图片存在~! \n"); return false; }   imshow("原始图",srcImage); //【2】创建和原始图一样的效果图,x重映射图,y重映射图 dstImage.create( srcImage.size(), srcImage.type() ); map_x.create( srcImage.size(), CV_32FC1 ); map_y.create( srcImage.size(), CV_32FC1 ); //【3】双层循环,遍历每一个像素点,改变map_x & map_y的值 for( int j = 0; j < srcImage.rows;j++) {   for( int i = 0; i < srcImage.cols;i++)  {   //改变map_x & map_y的值.    map_x.at<float>(j,i) = static_cast<float>(i);   map_y.at<float>(j,i) = static_cast<float>(srcImage.rows - j);  }  } //【4】进行重映射操作 remap( srcImage, dstImage, map_x, map_y, CV_INTER_LINEAR, BORDER_CONSTANT, Scalar(0,0, 0) ); //【5】显示效果图 imshow( "【程序窗口】", dstImage ); waitKey(); return 0;}


显示效果图:

 最近世界杯正如火如荼地进行着,这里的图片素材就是巴西队的球星们~

 



1.4 OpenCV2.X中remap函数源代码

 


这里我们放出remap函数的源码,供需要了解其实现细节的朋友们观看,浅墨在这里不花时间对其进行剖析。

void cv::remap( InputArray _src, OutputArray _dst,                InputArray _map1, InputArray _map2,                int interpolation, int borderType, const Scalar& borderValue ){    static RemapNNFunc nn_tab[] =    {        remapNearest<uchar>, remapNearest<schar>, remapNearest<ushort>, remapNearest<short>,        remapNearest<int>, remapNearest<float>, remapNearest<double>, 0    };    static RemapFunc linear_tab[] =    {        remapBilinear<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, RemapVec_8u, short>, 0,        remapBilinear<Cast<float, ushort>, RemapNoVec, float>,        remapBilinear<Cast<float, short>, RemapNoVec, float>, 0,        remapBilinear<Cast<float, float>, RemapNoVec, float>,        remapBilinear<Cast<double, double>, RemapNoVec, float>, 0    };    static RemapFunc cubic_tab[] =    {        remapBicubic<FixedPtCast<int, uchar, INTER_REMAP_COEF_BITS>, short, INTER_REMAP_COEF_SCALE>, 0,        remapBicubic<Cast<float, ushort>, float, 1>,        remapBicubic<Cast<float, short>, float, 1>, 0,        remapBicubic<Cast<float, float>, float, 1>,        remapBicubic<Cast<double, double>, float, 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值