注:本文學習自CVPR《Linear Spatial Pyramid Matching Using Sparse Coding
for Image Classification》、《Image classification By non-negative sparse coding, low-rank and sparse decomposition》及《基於稀疏編碼的圖像視覺特征提取及應用》
在提取全然部訓練圖像的SIFT特征后。須要對每幅圖像進行視覺特征編碼。
視覺特征編碼的目的在於對原始特征向量進行選擇和變換,得到圖像中最具表現力和區分度的視覺特征向量。使得計算機能夠更高效的進行處理。一般編碼方式是向量量化,還有一種視覺編碼方式稀疏編碼能更好的表示圖像。
1、向量量化
向量量化的基本思想是在基向量空間中尋找目標向量的近期鄰,然后用該基向量的編號表示原目標向量:

當中x為某個SIFT特征向量,di為基向量空間中的第i個向量。
事實上基向量就是對全部訓練圖像的全部SIFT特征向量進行聚類,得到的K個聚類中心。這K個特征向量最后作為基向量。然后對於每一幅圖像,尋找每一個SIFT特征向量屬於哪個基向量。來進行映射。
在向量量化的過程中,基本過程例如以下:
1) 將所有的訓練樣本進行歸一化;
2) 對訓練樣本進行聚類。得到若干個類中心,構成基向量空間:
3) 在全部類中心中為目標向量尋找近期鄰。
在BOW模型中,先聚類產生視覺關鍵詞,然后進行向量量化編碼。對於用SIFT特征

就是這幅圖像的稀疏編碼。
向量量化的長處在於計算簡單,數據壓縮率高。缺點在於精度損失比較大,在某些應用中難以滿足要求。
2、稀疏編碼
稀疏編碼的本質是一個目標向量能夠由少量的基向量經線性擬合而成,且基向量空間存在一定的冗余。
與向量量化的差別是向量量化的每一個目標向量僅僅能由一個基向量表示。也就是說向量量化方式的約束條件太嚴格。會引起重構誤差。二者差別可表演示樣例如以下:


對圖像的稀疏編碼一般分為兩個過程:
一是基向量的訓練過程,也稱為字典的學習。在這個過程中,我們利用大量的訓練樣本。通過無監督學習方法學習獲得一組冗余的基向量。這組基向量通常反映了訓練樣本中一些帶有本質特性的基元。如圖像中的邊界、角點,實驗表明,字典的學習過程模擬了人類視覺皮層對信息的處理過程。
最優化問題(1)變成了二次約束的最小二乘問題。即:
這個最優化問題,在給定X情況下,交替固定一個變量,訓練還有一個變量。如此迭代。
二是線性擬合的求解過程。即隨意目標向量xn都能夠由字典V內的若干個條目經線性組合擬合而成,該過程依據不同的約束條件,能夠得到不同的擬合系數un。然后用該系數向量表示圖像特征。
此時V已知。對圖像X稀疏編碼得到U,問題變為例如以下求解:

3、實驗過程:
1、從每張圖像中隨機提取一個特征點向量,湊出一個初始訓練樣本X。
(128*2600)
for ii = 1:2600
fpath = training.path{ii};
load(fpath);
num_fea = size(feaSet.feaArr, 2);
rndidx = randperm(num_fea);
X(:, ii) = feaSet.feaArr(:, rndidx(ii));
end;
2、視覺字典V的學習
a、初始視覺字典V通過隨機函數給出,先隨機產生一個128*300的矩陣作為初始視覺 字典
V = rand(128, 300)-0.5;%先隨機生成一個視覺詞典V
V = V - repmat(mean(V,1), size(V,1),1);
V = V*diag(1./sqrt(sum(V.*V)));
b、使用剛剛得到的V,對樣本X計算得到U
U = L1QP_FeatureSign_Set(X, V, lambda);
此函數在已知訓練樣本X和給出的視覺字典V的前提下,學習得到此時樣本的稀

c、使用剛剛得到的U,再訓練得到V
V = l2ls_learn_basis_dual(X, U, pars.VAR_basis);
此函數在已知訓練樣本X和樣本稀疏編碼U的前提下,學習得到V。在條件

d、迭代50次b和c過程,終於得到視覺詞典V及訓練樣本X的稀疏編碼U。
3、對每張圖像,應用得到的視覺字典V,得到其稀疏編碼U
4、例如以下代碼用某種方式(sc_approx_pooling)對每幅圖像的稀疏編碼進行了處理,然后用21*300(300是視覺關鍵詞的個數)維向量來表示這幅圖像。
曾經是對向量量化編碼U按關鍵詞出現的頻次計算直方圖來表示這幅圖像,如今改用最大池處理,即對於稀疏編碼得到的U,Uij表示了第i塊SIFT特征區域對第j個關鍵詞的歸屬程度,取每一個關鍵詞中歸屬程度的最大值來表示這個關鍵詞,得到K維特征向量來表示這幅圖像。
sc_fea = zeros(6300, 2600);%%全部訓練圖像的稀疏編碼
sc_label = zeros(2600, 1);
for iter1 = 1:2600,
fpath = database.path{iter1};
load(fpath);
%%對每張圖像給出一個稀疏編碼矩陣(這里須要對每張圖片每金字塔層每一個網格給出一個300*N的 稀疏編碼矩陣,最后按 權值串聯該幅圖的全部稀疏編碼作為終於稀疏編碼來表示這幅圖像)
sc_fea(:, iter1) = sc_approx_pooling(feaSet, V, pyramid, gamma);
sc_label(iter1) = database.label(iter1);
end;
總結一下,稀疏編碼事實上就是先對全部圖像的全部SIFT特征進行訓練,得到基向量也即視覺關鍵詞V。之后對於每一幅圖像,計算其每一個特征點所屬的基向量索引u。u中含有多個非零系數用來擬合多個基向量。得到一幅圖像的系數編碼U。
用U乘以基向量V就能表示一幅圖像X。之后再用方法(sc_approx_pooling)對每幅圖像的稀疏表示U進行了處理,得到300(視覺關鍵詞的個數)維向量來表示這幅圖像。