相关
SIFT原理与源码解析
SURF原理与源码解析
ORB原理与源码解析
FAST原理与源码解析
BRIEF描述子原理与源码解析
Harris原理与源码解析

转载请注明出处http://blog.csdn.net/luoshixian099/article/details/49174869

PCA-SIFT是对传统SIFT算法的改进,由Yan Ke等人在《PCA-SIFT: A More Distinctive Representation for Local Image Descriptors》中提出,论文中采用PCA(Principal Component Analysis)把SIFT特征描述子从128维降到了20维,优化了描述子占用的内存,同时提高了匹配的准确性。

复习SIFT原理步骤
1.构造DOG尺度空间 2.在各尺度上定位关键点 3.为关键点分配方向角 4.形成特征描述子 。
由于PCA-SIFT仅与SIFT第四步不同,1,2,3步骤详细过程请参考之前的文章SIFT原理。
步骤4:首先根据特征点所在尺度,确定一个特征点邻域(邻域大小与特征点所在尺度有关),分成4×4个子区域并旋转到主方向的位置,在每一子区域上统计梯度方向直方图(幅值采用采用高斯加权函数 ,360度范围被等分成8个方向),这样联合4×4个子区域统计信息就构成了一个特征描述子,特征描述子信息为4×4×8=128维。

—–PCA-SIFT原理步骤———————————————————————————————————–
1,2,3步骤与SIFT原理的相同,第四步(PCA):
(1)对特征点确定一个大小为41×41的邻域,旋转这个邻域到主方向;
(2)计算邻域内像素点的水平梯度与垂直梯度,这样每个特征点确定了一个大小为39×39×2=3042维的特征描述子;
(3)原论文中对同一类图像集中采集了21000个特征点,这样够成了一个原始特征矩阵M,矩阵大小3042×21000,计算矩阵的协方差矩阵N;
(4)计算协方差矩阵N的特征向量,根据特征根的大小排序,选择对应的前n个特征向量(论文中采用n=20),构成投影矩阵T;
(5)对新的特征描述子向量,乘以投影矩阵T,得到3042维降到n维的特征向量;

实际上,步骤(3),(4)是在之前计算好,即投影矩阵是通过同一类图像集采用PCA原理提前计算出。从图像中特征点计算得到3042维的特征描述子时,只需要与投影矩阵相乘,即可达到降维。关于投影矩阵的n的选择,可以根据需要固定n的值,也可根据协方差矩阵的特征值能量值百分比,自动确定n的大小。论文中采用n=20效果最佳。

.—————————————————————————————————————————————–

补充知识:
PCA(Principal Component Analysis)即主成分分析,也被称为KL变换或者Hotelling变换,数据的变换可以达到分类或者压缩数据的作用,PCA-SIFT是对SIFT描述子数据进行了压缩。首先收集数据所有特征(成分),通过变换的数据,观察数据的重要成分进行分类,也可以抛弃不重要的成分,减少或者压缩数据。如同,想表达某一种物体,而物体有很多个属性,通过变换数据,可以观察到每个属性的重要性,从而可以选择几种重要的属性去描述这一种物体,就到达了压缩数据的作用。

1 . 假如我们取到了有m个样本,每个样本有n个属性(行向量表示),则组成的数据矩阵
MY=(Y1,Y2,Y3,...Ym)MY=(Y1,Y2,Y3,...Ym);

2 . 计算协方差矩阵:即每两个随机变量之间的协方差构成的矩阵CYCY
协方差矩阵元素值表示两个随机变量的线性相关性,通过计算协方差可以确定两个数据集合之间是否有关系。协方差值的取值范围从0开始,0表示线性无关到反应依赖关系强烈的正值或者负值。注意,协方差只能衡量随机变量之间的线性关系,这也PCA的局限性。通过观察为0的值可以突出有利于分类的不相关特征。由协方差矩阵的定义,可知协方差矩阵是对称矩阵,而且对角线元素表示对应特征的方差。

3 . 计算协方差矩阵的特征值与特征向量
PCA通过即找到变换矩阵WW
即变换矩阵W由矩阵X的特征向量作为行向量构成;即求解矩阵X的对角化过程。
先求得矩阵X的特征值,特征值按大小排序,并求得特征值对应的特征向量构成变换矩阵W.

4 . 较大的特征值,表明此特征范围较大,方差也越大,容易区分。通常在压缩数据中,采用前几个较大的特征值对应的特征向量,构成变换矩阵。通过Z=XWTZ=XWT获得新特征,以缩减新特征对应的维数,且新特征是线性无关的。

5 . 有时为了从压缩后的数据重构原数据,被称为逆变换,X=ZWX=ZW,可以重构回原始数据特征。

/*
data: 为原始数据矩阵
mean: 各维度的均值,可以作为输入或者输出
flags: CV_COVAR_ROWS  表示每行作为一个样本;CV_COVAR_COLS  表示每列作为一个样本;CV_COVAR_USE_AVG  表示mean矩阵作为输入;...采用|操作联合
maxComponents: 需要的维数,必须小于样本数据的维数;
retainedVariance: 根据特征值能量百分比自动确定维数;
*/
class CV_EXPORTS PCA
{
public://! default constructorPCA();                                        //! the constructor that performs PCAPCA(InputArray data, InputArray mean, int flags, int maxComponents=0);   PCA(InputArray data, InputArray mean, int flags, double retainedVariance);//! operator that performs PCA. The previously stored data, if any, is releasedPCA& operator()(InputArray data, InputArray mean, int flags, int maxComponents=0);PCA& computeVar(InputArray data, InputArray mean, int flags, double retainedVariance);//! projects vector from the original space to the principal components subspaceMat project(InputArray vec) const;//投影函数//! projects vector from the original space to the principal components subspacevoid project(InputArray vec, OutputArray result) const;//投影函数//! reconstructs the original vector from the projectionMat backProject(InputArray vec) const;//逆变换操作//! reconstructs the original vector from the projectionvoid backProject(InputArray vec, OutputArray result) const;//逆变换操作Mat eigenvectors; //!< eigenvectors of the covariation matrix  特征向量矩阵Mat eigenvalues;  // !< eigenvalues of the covariation matrix  特征值矩阵,单列矩阵Mat mean; //!< mean value subtracted before the projection and added after the back  projection 特征均值矩阵
};
  • 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
  • 33
  • 34
  • 35
PCA& PCA::operator()(InputArray _data, InputArray __mean, int flags, int maxComponents)
{Mat data = _data.getMat(), _mean = __mean.getMat();int covar_flags = CV_COVAR_SCALE;//协方差元素取均值,即除以m   ,  m为原始数据的维数int i, len, in_count;Size mean_sz;CV_Assert( data.channels() == 1 );if( flags & CV_PCA_DATA_AS_COL )//表示数据样本向量按列存放{len = data.rows;  //表示数据的初始维数in_count = data.cols;  //表示数据的样本数covar_flags |= CV_COVAR_COLS;mean_sz = Size(1, len);//定义一个单列的矩阵尺寸}else{len = data.cols;in_count = data.rows;covar_flags |= CV_COVAR_ROWS;mean_sz = Size(len, 1);}int count = std::min(len, in_count), out_count = count;if( maxComponents > 0 )  //限制降维的数目out_count = std::min(count, maxComponents);// "scrambled" way to compute PCA (when cols(A)>rows(A)):// B = A'A; B*x=b*x; C = AA'; C*y=c*y -> AA'*y=c*y -> A'A*(A'*y)=c*(A'*y) -> c = b, x=A'*yif( len <= in_count )//样本数大于数据的维数,否则采用"scrmbled" way,协方差矩阵in_count×in_countcovar_flags |= CV_COVAR_NORMAL; //协方差矩阵大小为len×lenint ctype = std::max(CV_32F, data.depth());mean.create( mean_sz, ctype );//均值单行或者单列的矩阵Mat covar( count, count, ctype );if( _mean.data )  //采用提取计算好的均值矩阵{CV_Assert( _mean.size() == mean_sz );_mean.convertTo(mean, ctype);}/*计算协方差矩阵保存在covar*/calcCovarMatrix( data, covar, mean, covar_flags, ctype );  eigen( covar, eigenvalues, eigenvectors );//计算对称协方差矩阵的特征值与特征向量if( !(covar_flags & CV_COVAR_NORMAL) )  //“scrambled” 方法计算协方差矩阵{// CV_PCA_DATA_AS_ROW: cols(A)>rows(A). x=A'*y -> x'=y'*A// CV_PCA_DATA_AS_COL: rows(A)>cols(A). x=A''*y -> x'=y'*A'Mat tmp_data, tmp_mean = repeat(mean, data.rows/mean.rows, data.cols/mean.cols);if( data.type() != ctype || tmp_mean.data == mean.data ){data.convertTo( tmp_data, ctype );subtract( tmp_data, tmp_mean, tmp_data );}else{subtract( data, tmp_mean, tmp_mean );tmp_data = tmp_mean;}Mat evects1(count, len, ctype);gemm( eigenvectors, tmp_data, 1, Mat(), 0, evects1,(flags & CV_PCA_DATA_AS_COL) ? CV_GEMM_B_T : 0);eigenvectors = evects1;// normalize eigenvectorsfor( i = 0; i < out_count; i++ ){Mat vec = eigenvectors.row(i);normalize(vec, vec);}}if( count > out_count ){// use clone() to physically copy the data and thus deallocate the original matriceseigenvalues = eigenvalues.rowRange(0,out_count).clone();//保存特征值与特征向量eigenvectors = eigenvectors.rowRange(0,out_count).clone();//保存特征值与特征向量}return *this;
}
  • 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
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
void PCA::project(InputArray _data, OutputArray result) const
{Mat data = _data.getMat();CV_Assert( mean.data && eigenvectors.data &&((mean.rows == 1 && mean.cols == data.cols) || (mean.cols == 1 && mean.rows == data.rows)));Mat tmp_data, tmp_mean = repeat(mean, data.rows/mean.rows, data.cols/mean.cols); //扩展mean矩阵到_data大小,int ctype = mean.type();if( data.type() != ctype || tmp_mean.data == mean.data ){data.convertTo( tmp_data, ctype );subtract( tmp_data, tmp_mean, tmp_data );//  data-mean}else{subtract( data, tmp_mean, tmp_mean );tmp_data = tmp_mean;}if( mean.rows == 1 )gemm( tmp_data, eigenvectors, 1, Mat(), 0, result, GEMM_2_T );//输入矩阵乘以变换矩阵elsegemm( eigenvectors, tmp_data, 1, Mat(), 0, result, 0 );
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
void PCA::backProject(InputArray _data, OutputArray result) const //逆变换
{Mat data = _data.getMat();CV_Assert( mean.data && eigenvectors.data &&((mean.rows == 1 && eigenvectors.rows == data.cols) ||(mean.cols == 1 && eigenvectors.rows == data.rows)));Mat tmp_data, tmp_mean;data.convertTo(tmp_data, mean.type());if( mean.rows == 1 ){tmp_mean = repeat(mean, data.rows, 1);gemm( tmp_data, eigenvectors, 1, tmp_mean, 1, result, 0 );}else{tmp_mean = repeat(mean, 1, data.cols);gemm( eigenvectors, tmp_data, 1, tmp_mean, 1, result, GEMM_1_T );}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

参考:
PCA-SIFT: A More Distinctive Representation for Local Image Descriptors
http://blog.csdn.net/songzitea/article/details/18270457
http://www.360doc.com/content/14/0526/06/15831056_380900310.shtml

转载自:https://blog.csdn.net/luoshixian099/article/details/49174869

PCA-SIFT原理及源码解析相关推荐

  1. 【特征匹配】BRIEF特征描述子原理及源码解析

    相关:Fast原理及源码解析 Harris原理及源码解析 SIFT原理及源码解析 SURF原理及源码解析 转载请注明出处: http://blog.csdn.net/luoshixian099/art ...

  2. 【特征匹配】ORB原理与源码解析

    相关 : Fast原理与源码解析 Brief描述子原理与源码解析 Harris原理与源码解析 http://blog.csdn.net/luoshixian099/article/details/48 ...

  3. Redis进阶- Redisson分布式锁实现原理及源码解析

    文章目录 Pre 用法 Redisson分布式锁实现原理 Redisson分布式锁源码分析 redisson.getLock(lockKey) 的逻辑 redissonLock.lock()的逻辑 r ...

  4. SIFT原理与源码分析:DoG尺度空间构造

    <SIFT原理与源码分析>系列文章索引:http://blog.csdn.net/xiaowei_cqu/article/details/8069548 尺度空间理论 自然界中的物体随着观 ...

  5. Spring Boot 核心原理与源码解析 - 目录

    准备重新写 SpringBoot 配置文件解析原理 , 先在这里把要写的内容记下来 Spring Boot 核心原理与源码解析 - 目录 1\何时解析\如何解析 application.propert ...

  6. 视频教程-YOLOv3目标检测:原理与源码解析-计算机视觉

    YOLOv3目标检测:原理与源码解析 大学教授,美国归国博士.博士生导师:人工智能公司专家顾问:长期从事人工智能.物联网.大数据研究:已发表学术论文100多篇,授权发明专利10多项 白勇 ¥78.00 ...

  7. SpringMVC工作原理及源码解析

    SpringMVC工作原理及源码解析 一:SpringMVC原理图 二:SpringMVC的主要组件 1.前端控制器DispatcherServlet: 2.处理器映射器HandlerMapping: ...

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

    <SIFT原理与源码分析>系列文章索引:http://blog.csdn.net/xiaowei_cqu/article/details/8069548 由前一篇< 方向赋值> ...

  9. ORB_原理与源码解析

    原理文链接:https://blog.csdn.net/luoshixian099/article/details/48523267 为了满足实时性的要求,前面文章中介绍过快速提取特征点算法Fast, ...

最新文章

  1. 前端学HTTP之网关、隧道和中继
  2. 用命令行执行ROBOT FRAMEWORK
  3. django2.0.6 连接使用redis集群
  4. word List18
  5. 【贪心】Sunscreen(poj 3614/luogu 2887)
  6. ubuntu apt报错无法获得锁/var/lib/dpkg/lock 和无法锁定管理目录
  7. webserver之日志系统
  8. matlab 开采沉陷 何,MATLAB在开采沉陷预计可视化中的应用
  9. luoguP3799 妖梦拼木棒 [组合数学]
  10. Uber发布史上最简单的深度学习框架Ludwig!不懂编程也能玩转人工智能
  11. 1.material组件的安装及其使用
  12. codeforces-984D——XOR-pyramid(DP)
  13. Javascript:使用js将数据导出到excel/csv
  14. 机甲 java_战神金刚3(机甲版)
  15. Oracle 、SqlServer 根据日期逐日、逐月递增累加、逐行累加
  16. Go | 一分钟掌握Go | 9 - 通道
  17. win8系统桌面计算机,Win8计算机桌面管理软件
  18. UC浏览器怎样收藏视频?UC浏览器收藏视频的方法
  19. 【H5】html5的新增的标签和废除的标签
  20. android版本 51,51星变手机版

热门文章

  1. 图片服务 - thumbor成像
  2. 容器编排技术 -- Kubernetes 垃圾收集
  3. 容器编排技术 -- Kubernetes Pod 生命周期
  4. Mac下的Docker及Kubernetes(k8s)本地环境搭建与应用部署、管理界面kubernetes-dashboard
  5. Use Visual Studio Code to create and run Transact-SQL scripts for SQL Server
  6. c语言注释换颜色,C语言实现注释转换
  7. ogg mysql表结构不一致_OGG-01163 Bad column表结构一致、trail文件meta不一致处理
  8. Linux下压缩工具gzip和归档工具tar及其实战shell应用
  9. 【C语言】求s(n)=a+aa+aaa+...+aa...a的值
  10. freelance平台_完整的Freelance Web开发人员指南:如何通过Freelance编程工作来赚钱