まず、視覚的な単語の辞書を入手するか、具体的にする必要があります。kを使用してすべての画像のSIFT機能をクラスタリングする - クラスタリングを意味します。 [1]では、例えば、 64または256クラスタを推奨します。
そのためには、すべての記述子を1つの行列に連結してから、関数に渡す必要があります。さらに、vl_kmeans
関数は入力がsingle
またはdouble
のいずれかである必要があるため、記述子をuint8
からsingle
に変換します。
all_descr = single([sift_descr{:}]);
centroids = vl_kmeans(all_descr, 64);
第二に、あなたは寸法NumberOfClustersバイNumberOfDescriptors、クラスタに各ディスクリプタを割り当てている割り当て行列を、作成する必要があります。この割り当てマトリックスの作成には柔軟性があります。あなたはソフトまたはハード割り当てを行うことができます。あなたの裁量で単純な最近傍探索またはkd木または近似または近似近似スキームを使用できます。
チュートリアルでは、彼らはkdツリーを使用していますので、それに固執しましょう:まず、kdツリーを構築する必要があります。この操作は、右のcentroids
を見つけた後所属:
kdtree = vl_kdtreebuild(centroids);
はその後、我々は、画像ごとにVLADベクターを構築する準備が整いました。したがって、すべての画像を再解析し、VLADベクトルを独立して計算する必要があります。まず、チュートリアルの説明に従って、割り当てマトリックスを作成します。次に、vl_vlad
関数を使用してSIFT記述子をエンコードすることができます。 得VLADベクトルサイズにNumberOfClustersを有するであろう* SiftDescriptorSize、すなわちこの例では64 * 128 ..
enc = zeros(64*128, numel(sift_descr));
for k=1:numel(sift_descr)
% Create assignment matrix
nn = vl_kdtreequery(kdtree, centroids, single(sift_descr{k}));
assignments = zeros(64, numel(nn), 'single');
assignments(sub2ind(size(assignments)), nn, 1:numel(nn))) = 1;
% Encode using VLAD
enc(:, k) = vl_vlad(single(sift_descr{k}), centroids, assignments);
end
最後に、我々は、データベース内のすべての画像のために高次元VLADベクトルを有します。通常、VLAD記述子の次元数を減らすことが望まれます。 PCAを使用します。
さて、データベースにない新しいイメージ与えられた、あなたは、SIFTはvl_sift
を使用しています抽出できvl_kdtreequery
に割り当てマトリックスを作成し、vl_vlad
を使用して、その画像のためVLADベクトルを作成します。だから、あなたは新しい重心を見つけたり、新しいKD-ツリーを作成する必要はありません。
% Load image and extract SIFT features
new_image = imread('filename.jpg');
new_image = single(rgb2gray(new_image));
[~, new_sift] = vl_sift(new_image);
% Create assignment matrix
nn = vl_kdtreequery(kdtree, centroids, single(new_sift));
assignments = zeros(64, numel(nn), 'single');
assignments(sub2ind(size(assignments)), nn, 1:numel(nn))) = 1;
% Encode using VLAD
new_vlad = vl_vlad(single(new_sift), centroids, assignments);
[1] Arandjelovic、R.、& Zisserman、A.(2013)。 VLADについてコンピュータビジョンとパターン認識に関するIEEE会議(CVPR)、1578-1585。 https://doi.org/10.1109/CVPR.2013.207
偉大な回答、ありがとうございます。 –