《SIFT原理与源码分析》系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html

由前一篇《关键点搜索与定位》,我们已经找到了关键点。为了实现图像旋转不变性,需要根据检测到的关键点局部图像结构为特征点方向赋值。也就是在findScaleSpaceExtrema()函数里看到的alcOrientationHist()语句:

// 计算梯度直方图
float omax = calcOrientationHist(gauss_pyr[o*(nOctaveLayers+) + layer],
Point(c1, r1),
cvRound(SIFT_ORI_RADIUS * scl_octv),
SIFT_ORI_SIG_FCTR * scl_octv,
hist, n);
我们使用图像的梯度直方图法求关键点局部结构的稳定方向。

梯度方向和幅值

在前文中,精确定位关键点后也找到改特征点的尺度值σ,根据这一尺度值,得到最接近这一尺度值的高斯图像:

使用有限差分,计算以关键点为中心,以3×1.5σ为半径的区域内图像梯度的幅角和幅值,公式如下:

梯度直方图

在完成关键点邻域内高斯图像梯度计算后,使用直方图统计邻域内像素对应的梯度方向和幅值。

有关直方图的基础知识可以参考《数字图像直方图》,可以看做是离散点的概率表示形式。此处方向直方图的核心是统计以关键点为原点,一定区域内的图像像素点对关键点方向生成所作的贡献。

梯度方向直方图的横轴是梯度方向角,纵轴是剃度方向角对应的梯度幅值累加值。梯度方向直方图将0°~360°的范围分为36个柱,每10°为一个柱。下图是从高斯图像上求取梯度,再由梯度得到梯度方向直方图的例图。

在计算直方图时,每个加入直方图的采样点都使用圆形高斯函数函数进行了加权处理,也就是进行高斯平滑。这主要是因为SIFT算法只考虑了尺度和旋转不变形,没有考虑仿射不变性。通过高斯平滑,可以使关键点附近的梯度幅值有较大权重,从而部分弥补没考虑仿射不变形产生的特征点不稳定。

通常离散的梯度直方图要进行插值拟合处理,以求取更精确的方向角度值。(这和《关键点搜索与定位》中插值的思路是一样的)。

关键点方向

直方图峰值代表该关键点处邻域内图像梯度的主方向,也就是该关键点的主方向。在梯度方向直方图中,当存在另一个相当于主峰值    80%能量的峰值时,则将这个方向认为是该关键点的辅方向。所以一个关键点可能检测得到多个方向,这可以增强匹配的鲁棒性。Lowe的论文指出大概有15%关键点具有多方向,但这些点对匹配的稳定性至为关键。

获得图像关键点主方向后,每个关键点有三个信息(x,y,σ,θ):位置、尺度、方向。由此我们可以确定一个SIFT特征区域。通常使用一个带箭头的圆或直接使用箭头表示SIFT区域的三个值:中心表示特征点位置,半径表示关键点尺度(r=2.5σ),箭头表示主方向。具有多个方向的关键点可以复制成多份,然后将方向值分别赋给复制后的关键点。如下图:

源码

// Computes a gradient orientation histogram at a specified pixel
// 计算特定点的梯度方向直方图
static float calcOrientationHist( const Mat& img, Point pt, int radius,
float sigma, float* hist, int n )
{
//len:2r+1也就是以r为半径的圆(正方形)像素个数
int i, j, k, len = (radius*+)*(radius*+); float expf_scale = -.f/(.f * sigma * sigma);
AutoBuffer<float> buf(len* + n+);
float *X = buf, *Y = X + len, *Mag = X, *Ori = Y + len, *W = Ori + len;
float* temphist = W + len + ; for( i = ; i < n; i++ )
temphist[i] = .f; // 图像梯度直方图统计的像素范围
for( i = -radius, k = ; i <= radius; i++ )
{
int y = pt.y + i;
if( y <= || y >= img.rows - )
continue;
for( j = -radius; j <= radius; j++ )
{
int x = pt.x + j;
if( x <= || x >= img.cols - )
continue; float dx = (float)(img.at<short>(y, x+) - img.at<short>(y, x-));
float dy = (float)(img.at<short>(y-, x) - img.at<short>(y+, x)); X[k] = dx; Y[k] = dy; W[k] = (i*i + j*j)*expf_scale;
k++;
}
} len = k; // compute gradient values, orientations and the weights over the pixel neighborhood
exp(W, W, len);
fastAtan2(Y, X, Ori, len, true);
magnitude(X, Y, Mag, len); // 计算直方图的每个bin
for( k = ; k < len; k++ )
{
int bin = cvRound((n/.f)*Ori[k]);
if( bin >= n )
bin -= n;
if( bin < )
bin += n;
temphist[bin] += W[k]*Mag[k];
} // smooth the histogram
// 高斯平滑
temphist[-] = temphist[n-];
temphist[-] = temphist[n-];
temphist[n] = temphist[];
temphist[n+] = temphist[];
for( i = ; i < n; i++ )
{
hist[i] = (temphist[i-] + temphist[i+])*(.f/.f) +
(temphist[i-] + temphist[i+])*(.f/.f) +
temphist[i]*(.f/.f);
} // 得到主方向
float maxval = hist[];
for( i = ; i < n; i++ )
maxval = std::max(maxval, hist[i]); return maxval;
}

这一步比较简单~参见《SIFT原理与源码分析》。

本文转自:http://blog.csdn.net/xiaowei_cqu/article/details/8096072

【OpenCV】SIFT原理与源码分析:方向赋值的更多相关文章

  1. OpenCV SIFT原理与源码分析

    http://blog.csdn.net/xiaowei_cqu/article/details/8069548 SIFT简介 Scale Invariant Feature Transform,尺度 ...

  2. 【OpenCV】SIFT原理与源码分析:DoG尺度空间构造

    原文地址:http://blog.csdn.net/xiaowei_cqu/article/details/8067881 尺度空间理论   自然界中的物体随着观测尺度不同有不同的表现形态.例如我们形 ...

  3. 【OpenCV】SIFT原理与源码分析:关键点描述

    <SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一篇<方向赋值>,为找到的关键点即SI ...

  4. 【OpenCV】SIFT原理与源码分析:关键点搜索与定位

    <SIFT原理与源码分析>系列文章索引:http://www.cnblogs.com/tianyalu/p/5467813.html 由前一步<DoG尺度空间构造>,我们得到了 ...

  5. 【OpenCV】SIFT原理与源码分析

    SIFT简介 Scale Invariant Feature Transform,尺度不变特征变换匹配算法,是由David G. Lowe在1999年(<Object Recognition f ...

  6. OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波

    http://blog.csdn.net/chenyusiyuan/article/details/8710462 OpenCV学习笔记(27)KAZE 算法原理与源码分析(一)非线性扩散滤波 201 ...

  7. ConcurrentHashMap实现原理及源码分析

    ConcurrentHashMap实现原理 ConcurrentHashMap源码分析 总结 ConcurrentHashMap是Java并发包中提供的一个线程安全且高效的HashMap实现(若对Ha ...

  8. HashMap和ConcurrentHashMap实现原理及源码分析

    HashMap实现原理及源码分析 哈希表(hash table)也叫散列表,是一种非常重要的数据结构,应用场景及其丰富,许多缓存技术(比如memcached)的核心其实就是在内存中维护一张大的哈希表, ...

  9. (转)ReentrantLock实现原理及源码分析

    背景:ReetrantLock底层是基于AQS实现的(CAS+CHL),有公平和非公平两种区别. 这种底层机制,很有必要通过跟踪源码来进行分析. 参考 ReentrantLock实现原理及源码分析 源 ...

随机推荐

  1. python购物车优化

    一.需求分析 拥有用户接口和商家接口 用户能够进行消费记录查询,充值,购物等功能,消费记录存储于数据库 商家可以进行商品的增删改等操作 二.程序流程图 程序大致流程图如下: 三.代码实现 本程序分成两 ...

  2. 一个网页从输入URL到页面加载完的过程

    过程概述 1.浏览器查找域名对应的IP地址 2.浏览器根据IP地址与服务器建立socket连接 3.浏览器与服务器通信:浏览器请求,服务器处理请求和响应 4.浏览器与服务器断开连接 具体过程 1.搜索 ...

  3. Buy the Ticket HDU 1133 卡特兰数应用+Java大数

    Problem Description The "Harry Potter and the Goblet of Fire" will be on show in the next ...

  4. Scrum立会报告+燃尽图(十一月十五日总第二十三次):代码规范与技术交流

    此作业要求参见:https://edu.cnblogs.com/campus/nenu/2018fall/homework/2384 项目地址:https://git.coding.net/zhang ...

  5. c# 修改exe.config文件并且及时更新

    1.config文件地址:AppDomain.CurrentDomain.SetupInformation.ConfigurationFile 注意:如果是在调试程序中运行,此地址指代的是vhost. ...

  6. hdu1242 Rescue DFS(路径探索题)

    这里我定义的路径探索题指 找某路能够到达目的地,每次走都有方向,由于是探索性的走 之后要后退 那些走过的状态都还原掉 地址:http://acm.hdu.edu.cn/showproblem.php? ...

  7. 软件图书,偏.net方向

    深入理解计算机系统(原书第2版) 作者:Randal E.Bryant:1981年在麻省理工学院获计算机科学博士学位,现任美国卡内基·梅隆大学计算机学院院长 内容: 深入浅出地介绍了处理器.编译器.操 ...

  8. TCP系列44—拥塞控制—7、SACK关闭的快速恢复

    ) return;    delta = ssthresh - in_flight;     prr_delivered += newly_acked_sacked; if (delta < 0 ...

  9. 各大巨头电商提供的IP库API接口-新浪、搜狐、阿里

    新浪的IP地址查询接口:http://int.dpool.sina.com.cn/iplookup/iplookup.php?format=js     (不可用)新浪多地域测试方法:http://i ...

  10. App流量测试--使用安卓自身提供的TCP收发长度统计功能

    在Linux系统有3个地方保存流量统计文件,对于Android系统同样也适用: (1)在/proc/net/dev下可以查看各个网络接口的收发流量  (等同adb shell cat /proc/pi ...