热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

分析OpenSurf(2)

①积分图像的实现首先在Integral.cpp里面找到Integral(),如下:IplImage*Integral(IplImage*source)

①积分图像的实现

 首先在Integral.cpp里面找到Integral(),如下:

IplImage *Integral(IplImage *source)
{//转换成单通道图像 convert the image to single channel 32fIplImage *img = getGray(source);IplImage *int_img = cvCreateImage(cvGetSize(img), IPL_DEPTH_32F, 1);//给变量赋值 set up variables for data accessint height = img->height;int width = img->width;int step = img->widthStep/sizeof(float);float *data = (float *) img->imageData; float *i_data = (float *) int_img->imageData; //仅限第一行 first row onlyfloat rs = 0.0f;for(int j=0; j}

1.  首先将原输入转化为灰度图像,并创建一个大小等于灰度图像gray-image的图像数组--积分图像int_img。

2.  获取图像的信息,比如大小(高height和宽width)以及gray-image和积分图像int_img的数据首地址data && i_data。(注意此时数据类型为float)

3.  首先计算第一行像素的积分值,相当于一维数据的累加。其他数据通过迭代计算获取,i_data[i*step+j] = rs + i_data[(i-1)*step+j],若当前点为(i,j),其中rs就为第 i 行第 j 列之前(包括第 i 行第 j 列)所有像素值和。 如下所示:

                                        

 [其中黑色为当前点i_data[i*step+j],绿色为当前点同一列上一行的点i_data[(i-1)*step+j],而rs=横放着的和黑色点同行的那块矩形框对应的区域像素值之和]

4.  释放灰度图像,并返回积分图像。

 

integral.h中的相关函数:  BoxIntegral().

inline float BoxIntegral(IplImage *img, int row, int col, int rows, int cols)

其中,几个参数意思分别为源图像,row,col为A点的坐标值,rows和cols分别为高和宽。

利用上面的积分图像计算   A      B   这样的box区域里面所有像素点的灰度值之和。S=int_img(D)+int_img(A)-int_img(B)-int_img(C).

                                         C      D 



②Hessian矩阵特征的计算

FastHessian,计算hessian矩阵的类,它的定义在fasthessian.h里,实现在fasthessian.cpp里。

class FastHessian {public://! Constructor without imageFastHessian(std::vector &ipts, const int octaves = OCTAVES, const int intervals = INTERVALS, const int init_sample = INIT_SAMPLE, const float thres = THRES);//! Constructor with imageFastHessian(IplImage *img, std::vector &ipts, const int octaves = OCTAVES, const int intervals = INTERVALS, const int init_sample = INIT_SAMPLE, const float thres = THRES);//! Destructor~FastHessian();//! Save the parametersvoid saveParameters(const int octaves, const int intervals,const int init_sample, const float thres);//!设置或重设源积分图像 Set or re-set the integral image sourcevoid setIntImage(IplImage *img);//!寻找图像特征并写入特征向量 Find the image features and write into vector of featuresvoid getIpoints();private://---------------- Private Functions -----------------////! Build map of DoH(Determinant of Hessian) responsesvoid buildResponseMap();//! Calculate DoH responses for supplied layervoid buildResponseLayer(ResponseLayer *r);//! 3x3x3 Extrema testint isExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b); //! 插值函数Interpolation functions - adapted from Lowe's SIFT implementationvoid interpolateExtremum(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);void interpolateStep(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b,double* xi, double* xr, double* xc );CvMat* deriv3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);CvMat* hessian3D(int r, int c, ResponseLayer *t, ResponseLayer *m, ResponseLayer *b);//---------------- Private Variables -----------------////! Pointer to the integral Image, and its attributes IplImage *img;int i_width, i_height;//! Reference to vector of features passed from outside std::vector &ipts;//!海森矩阵行列式的响应栈 Response stack of determinant of hessian valuesstd::vector responseMap;//! 高斯金字塔的组数int octaves;//! 每组的层数int intervals;//! 特征点检测的初始抽样步骤 Initial sampling step for Ipoint detectionint init_sample;//! Threshold value for blob resonsesfloat thresh;
};

在public里面定义了两种构造函数分别对应有无源图像这一项参数,紧接着还定义了析构函数~FastHessian等函数。下面在fasthessian.cpp对这些函数的实现一一解释:

两个构造函数都是调用了saveParameters(octaves, intervals, init_sample, thresh)设置构造金字塔的参数,而带图像的构造函数另外多加了一句setIntImage(img)用来设置当前图像。

//! Save the parameters
void FastHessian::saveParameters(const int octaves, const int intervals, const int init_sample, const float thresh)
{// Initialise variables with bounds-checked valuesthis->octaves &#61; (octaves > 0 && octaves <&#61; 4 ? octaves : OCTAVES);this->intervals &#61; (intervals > 0 && intervals <&#61; 4 ? intervals : INTERVALS);this->init_sample &#61; (init_sample > 0 && init_sample <&#61; 6 ? init_sample : INIT_SAMPLE);this->thresh &#61; (thresh >&#61; 0 ? thresh : THRES);
}//! Set or re-set the integral image source
void FastHessian::setIntImage(IplImage *img)
{// Change the source imagethis->img &#61; img;i_height &#61; img->height;i_width &#61; img->width;
}

由于在h头文件中已设置

static const int OCTAVES &#61; 5;//组数
static const int INTERVALS &#61; 4;//每组层数
static const float THRES &#61; 0.0004f;//阈值
static const int INIT_SAMPLE &#61; 2;//初始采样因子

所以 saveParameters的作用就是调整参数&#xff0c;以防过大或过小。

FastHessian::getIpoints()提取兴趣点&#xff1a;

//! Find the image features and write into vector of features
void FastHessian::getIpoints()
{// filter index mapstatic const int filter_map [OCTAVES][INTERVALS] &#61; {{0,1,2,3}, {1,3,4,5}, {3,5,6,7}, {5,7,8,9}, {7,9,10,11}};// Clear the vector of exisiting iptsipts.clear();// Build the response mapbuildResponseMap();// Get the response layers...
...
}

首先初始化filter_map&#xff0c;清空标记特征点的ipts结构体。

 创建高斯平滑层函数参数ResponseMap()&#xff0c;大小与论文所给完全一致&#xff0c;

         // Oct1: 9, 15, 21, 27
         // Oct2: 15, 27, 39, 51
         // Oct3: 27, 51, 75, 99
         // Oct4: 51, 99, 147,195
         // Oct5: 99, 195,291,387

这些都是每组模板的大小&#xff0c;每组间隔递增&#xff0c;6,12,24,48,96 。ResponseMap这个结构体向量包含4个参数ResponseLayer(int width, int height, int step, int filter)定义在responsemap.h里面&#xff0c;其中width和height等于实际图像大小除以step(step初始值为2)&#xff0c;而filter则是滤波器半径。

 

然后使用buildResponseLayer(responseMap[i])对图像处理后将数据存放在responses和laplacian两个数组里面。

void FastHessian::buildResponseLayer(ResponseLayer *rl)
{float *responses &#61; rl->responses; // response storageunsigned char *laplacian &#61; rl->laplacian; // laplacian sign storageint step &#61; rl->step; // step size for this filter 滤波器尺度因子int b &#61; (rl->filter - 1) / 2; // border for this filter 滤波器边界int l &#61; rl->filter / 3; // lobe for this filter (filter size / 3)int w &#61; rl->filter; // filter size 滤波器大小float inverse_area &#61; 1.f/(w*w); // normalisation factor 标准化因子float Dxx, Dyy, Dxy;for(int r, c, ar &#61; 0, index &#61; 0; ar height; &#43;&#43;ar) {for(int ac &#61; 0; ac width; &#43;&#43;ac, index&#43;&#43;) {// get the image coordinatesr &#61; ar * step;c &#61; ac * step; // Compute response componentsDxx &#61; BoxIntegral(img, r - l &#43; 1, c - b, 2*l - 1, w)- BoxIntegral(img, r - l &#43; 1, c - l / 2, 2*l - 1, l)*3;Dyy &#61; BoxIntegral(img, r - b, c - l &#43; 1, w, 2*l - 1)- BoxIntegral(img, r - l / 2, c - l &#43; 1, l, 2*l - 1)*3;Dxy &#61; &#43; BoxIntegral(img, r - l, c &#43; 1, l, l)&#43; BoxIntegral(img, r &#43; 1, c - l, l, l)- BoxIntegral(img, r - l, c - l, l, l)- BoxIntegral(img, r &#43; 1, c &#43; 1, l, l);// Normalise the filter responses with respect to their sizeDxx *&#61; inverse_area;Dyy *&#61; inverse_area;Dxy *&#61; inverse_area;// Get the determinant of hessian response & laplacian signresponses[index] &#61; (Dxx * Dyy - 0.81f * Dxy * Dxy);laplacian[index] &#61; (Dxx &#43; Dyy >&#61; 0 ? 1 : 0);#ifdef RL_DEBUG// create list of the image coords for each responserl->coords.push_back(std::make_pair(r,c));
#endif}}
}

其中计算Dxy和Dyy的示意图如下&#xff0c;其他的Dxx(Dyy的转置)读者自己参考。【此时w&#61;9,l&#61;9/3&#61;3,对应于右图的总计算区域高度和宽度2*l-1】

 

         

  圆点为当前点&#xff0c;将红色方形区域1内的积分值减去绿色方形2区域内的积分值&#61;Dxy*w2                 

 绿色方形区域2内的积分值减去2*红色色方形区域1内的积分值&#61;Dyy*w2 (&#61;&#61;用一整块区域-3*红色区域&#xff09;

 最后将计算后的结果存放到ResponseLayer里面的response和laplacian一维数组里&#xff0c;数组的大小即为ResponseLayer->width * ResponseLayer->width。

 

这样就计算出了每一层的所有像素点的det(Happrox)&#61;Dxx*Dyy-(0.9*Dxy)2,下面开始判断当前点是否是极值点。






















推荐阅读
  • 本文介绍了使用哈夫曼树实现文件压缩和解压的方法。首先对数据结构课程设计中的代码进行了分析,包括使用时间调用、常量定义和统计文件中各个字符时相关的结构体。然后讨论了哈夫曼树的实现原理和算法。最后介绍了文件压缩和解压的具体步骤,包括字符统计、构建哈夫曼树、生成编码表、编码和解码过程。通过实例演示了文件压缩和解压的效果。本文的内容对于理解哈夫曼树的实现原理和应用具有一定的参考价值。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
  • [大整数乘法] java代码实现
    本文介绍了使用java代码实现大整数乘法的过程,同时也涉及到大整数加法和大整数减法的计算方法。通过分治算法来提高计算效率,并对算法的时间复杂度进行了研究。详细代码实现请参考文章链接。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • This article discusses the efficiency of using char str[] and char *str and whether there is any reason to prefer one over the other. It explains the difference between the two and provides an example to illustrate their usage. ... [详细]
  • SpringMVC接收请求参数的方式总结
    本文总结了在SpringMVC开发中处理控制器参数的各种方式,包括处理使用@RequestParam注解的参数、MultipartFile类型参数和Simple类型参数的RequestParamMethodArgumentResolver,处理@RequestBody注解的参数的RequestResponseBodyMethodProcessor,以及PathVariableMapMethodArgumentResol等子类。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • 本文介绍了如何在给定的有序字符序列中插入新字符,并保持序列的有序性。通过示例代码演示了插入过程,以及插入后的字符序列。 ... [详细]
  • 1,关于死锁的理解死锁,我们可以简单的理解为是两个线程同时使用同一资源,两个线程又得不到相应的资源而造成永无相互等待的情况。 2,模拟死锁背景介绍:我们创建一个朋友 ... [详细]
  • PHP中的单例模式与静态变量的区别及使用方法
    本文介绍了PHP中的单例模式与静态变量的区别及使用方法。在PHP中,静态变量的存活周期仅仅是每次PHP的会话周期,与Java、C++不同。静态变量在PHP中的作用域仅限于当前文件内,在函数或类中可以传递变量。本文还通过示例代码解释了静态变量在函数和类中的使用方法,并说明了静态变量的生命周期与结构体的生命周期相关联。同时,本文还介绍了静态变量在类中的使用方法,并通过示例代码展示了如何在类中使用静态变量。 ... [详细]
  • 本文探讨了C语言中指针的应用与价值,指针在C语言中具有灵活性和可变性,通过指针可以操作系统内存和控制外部I/O端口。文章介绍了指针变量和指针的指向变量的含义和用法,以及判断变量数据类型和指向变量或成员变量的类型的方法。还讨论了指针访问数组元素和下标法数组元素的等价关系,以及指针作为函数参数可以改变主调函数变量的值的特点。此外,文章还提到了指针在动态存储分配、链表创建和相关操作中的应用,以及类成员指针与外部变量的区分方法。通过本文的阐述,读者可以更好地理解和应用C语言中的指针。 ... [详细]
  • 本文介绍了在Vue项目中如何结合Element UI解决连续上传多张图片及图片编辑的问题。作者强调了在编码前要明确需求和所需要的结果,并详细描述了自己的代码实现过程。 ... [详细]
  • 猜字母游戏
    猜字母游戏猜字母游戏——设计数据结构猜字母游戏——设计程序结构猜字母游戏——实现字母生成方法猜字母游戏——实现字母检测方法猜字母游戏——实现主方法1猜字母游戏——设计数据结构1.1 ... [详细]
  • 本文讨论了编写可保护的代码的重要性,包括提高代码的可读性、可调试性和直观性。同时介绍了优化代码的方法,如代码格式化、解释函数和提炼函数等。还提到了一些常见的坏代码味道,如不规范的命名、重复代码、过长的函数和参数列表等。最后,介绍了如何处理数据泥团和进行函数重构,以提高代码质量和可维护性。 ... [详细]
  • Java SE从入门到放弃(三)的逻辑运算符详解
    本文详细介绍了Java SE中的逻辑运算符,包括逻辑运算符的操作和运算结果,以及与运算符的不同之处。通过代码演示,展示了逻辑运算符的使用方法和注意事项。文章以Java SE从入门到放弃(三)为背景,对逻辑运算符进行了深入的解析。 ... [详细]
author-avatar
哭着说再见0
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有