PCA对特征点描述子降维
降維在機器學(xué)習(xí)領(lǐng)域其實是很重要的一部分,因為在高維情形下回出現(xiàn)樣本稀疏,計算距離、內(nèi)積困難,是所有機器學(xué)習(xí)面臨的共同問題,被稱為維數(shù)災(zāi)難(Curse of dimensionality),而降維就是解決的一個辦法,它不僅讓運算量變簡單,還因為將原始數(shù)據(jù)投影在主特征分量上可以抵抗一些噪聲的干擾。因為想通過降維來縮小圖像配準(zhǔn)過程中特征點匹配的運算量,也在公眾號機器學(xué)習(xí)算法工程師中看到了一些降維的方法,比如PCA、核化(kernelized,應(yīng)該就是核機制吧,實現(xiàn)非線性降維)、流行學(xué)習(xí)、度量學(xué)習(xí)。當(dāng)然最成熟的還是PCA,雖然很早就出現(xiàn)了PCA-SIFT,但還是想先自己動手實現(xiàn)一下。思路是先導(dǎo)出Lowe格式的特征點txt文件,然后再在import的時候修改函數(shù)降維,寫入descr_pca數(shù)組中再導(dǎo)出,得到64維的特征點。這時再導(dǎo)入降維之后的數(shù)據(jù),通過這些數(shù)據(jù)來實現(xiàn)圖像配準(zhǔn)。
這時候就又出現(xiàn)問題了,構(gòu)建kd樹的過程很慢,而且無法得到配準(zhǔn)結(jié)果。后來才意識到自己用的boat的圖像的特征點數(shù)據(jù)卻在實驗中用的beaver圖像,當(dāng)改正這個錯誤,并且導(dǎo)入原始的特征點數(shù)據(jù)后做實驗,結(jié)果匹配對的錯誤率很高,懷疑是不是因為stack_imgs把兩幅圖像顯示在一起,造成坐標(biāo)變換的原因。但是最起碼img1部分的特征點應(yīng)該正常啊,現(xiàn)在的情況是完全不對。。
從調(diào)試情況來看,import部分沒有問題,第一個點都是(254,297),對應(yīng)的第二幅圖中檢測到的是(134,258),與txt中的數(shù)據(jù)吻合。在Lowe格式的txt特征點文件中,第一行是特征點個數(shù)和描述子維數(shù),對每一個特征點,第一行四個數(shù)據(jù)依次是特征點的y坐標(biāo),x坐標(biāo),特征點的尺度,特征點的方向,然后是128個double型數(shù)字https://blog.csdn.net/masibuaa/article/details/9204157。問題似乎出在構(gòu)建kd樹之后的尋找匹配對的過程中。Kd樹是對圖2的特征點feat2構(gòu)建的,對feat1中的特征點遍歷,在kd樹中尋找對應(yīng)的匹配點。找到的第一對是(3,15)-(4,20).
源碼,尤其是c語言,對指針的運用真的是好復(fù)雜。如下,在導(dǎo)入特征點中和對kd樹中進行knn查找的過程中分別有兩重指針和三重指針。
static int import_lowe_features( char*filename, struct feature** features )//靜態(tài)函數(shù),不能被其他文件使用,所以其他文件也可以有相同的函數(shù)名
int kdtree_bbf_knn( struct kd_node*kd_root, struct feature* feat, int k,
?????????????????? ??? struct feature*** nbrs, int max_nn_chks )
在import_lowe_features函數(shù)中,有下面關(guān)鍵的兩句:
f = calloc( n, sizeof(struct feature) );//在內(nèi)存的動態(tài)存儲區(qū)中分配n個長度為size的連續(xù)空間,函數(shù)返回一個指向分配起始地址的指針
*features = f;//相當(dāng)于feature=&f??把features復(fù)數(shù)指向f //首地址賦給*features
于是,將import_features(path1, 1, &feat1);改為import_features(path1,1, import_feat1);//第三個參數(shù)是指針的指針,struct feature** import_feat1=NULL//初始化,運行的時候異常。
看來還是要用&feat1,因為源碼中原始的特征點檢測也是這么寫的:n1 = sift_features( img1, &feat1 );
后來發(fā)現(xiàn)在?? feat = feat1 + i;//指針的加法 之前,動態(tài)分配長度為n的內(nèi)存之后,fscanf坐標(biāo)值的時候就出錯了。fscanf讀取txt文件,要求txt文件編碼方式為ANSI,這個沒有出錯。
fscanf( file, " %lf %lf %lf %lf", &y, &x, &s, &o ) != 4 )//%lf是double類型輸入 fscanf返回讀取的長度
兩個格式控制符%lf之間是空格,適用于數(shù)據(jù)之間是空格,若數(shù)據(jù)之間是逗號,格式控制符之間也是逗號,這個也沒有出錯。
結(jié)果,尷尬了,一步步調(diào)試,看第一個特征點的各個參數(shù),坐標(biāo)是對的,一個個看128維描述子,發(fā)現(xiàn)到64的時候就跳變?yōu)榈诙€特征點了。真相大白,原來是自己在做導(dǎo)入降維后的txt文件時把d修改為64,在這里驗證128維的時候忘記改回去了。。
如下是按照lowe格式導(dǎo)入特征點信息做的圖像配準(zhǔn):
其中特征點導(dǎo)入費時4s左右。
這是直接對圖像做的特征點檢測和配準(zhǔn):
其中特征點檢測就耗時26s
回頭再看導(dǎo)入64維的描述子。速度奇慢,且無法完成配準(zhǔn)。報錯說找到的匹配對太少。打開降維后的txt文件:
7875 64
297.440434 254.241265 80.338874 -1.866019
?2 01 0 0 0 0 0 -1 0 0 0 0 0 0 0 -1 0 0 0
?0 00 0 3 0 0 0 0 0 0 0 0 0 -1 0 0 0 0 0
?-1 00 0 0 0 0 0 -1 0 0 0 0 0 0 0 0 1 0 0
?0 00 0
557.449920 181.560168 42.599985 1.464965
?4 -10 -1 0 0 0 3 0 0 1 0 0 0 0 0 -1 -1 0 0
?0 00 0 0 -2 1 0 0 0 0 0 3 1 -1 1 0 0 0 1
?0 21 0 0 0 0 -1 -3 0 -1 0 0 0 0 -1 -2 0 0 0
?0 00 -1
可以看到64個特征數(shù)據(jù),分為20*3+4.而在導(dǎo)入的時候,特征點的坐標(biāo)是取一行四個數(shù)值那行的前兩個值的,這樣就會把一部分描述子也誤當(dāng)做坐標(biāo)值和尺度大小即梯度。
Pcad 過程中對特征值和特征向量的行列數(shù)還是認識不夠,最后將result寫成方陣才不中斷。后來導(dǎo)出成了4*4維的描述子。這樣再導(dǎo)入到程序中來配準(zhǔn),找到500多個匹配對,但是畫不出匹配的連線。調(diào)試過程中發(fā)現(xiàn)匹配對也不正確,會不會是降維后kd樹中查找knn中閾值也要改變。
總結(jié)
以上是生活随笔為你收集整理的PCA对特征点描述子降维的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 耗时n年,38页《数据仓库知识体系.pd
- 下一篇: dataframe常用操作总结