Извлечение VLAD из дескрипторов SIFT в VLFeat с помощью Matlab
У меня есть папка с изображениями. Я хочу вычислить особенности VLAD для каждого изображения.
Я зацикливаюсь на каждом изображении, загружаю его и получаю дескрипторы SIFT следующим образом:
repo = '/media/data/images/';
filelist = dir([repo '*.jpg']);
sift_descr = {}
for i = 1:size(filelist, 1)
I = imread([repo filelist(i).name]) ;
I = single(rgb2gray(I)) ;
[f,d] = vl_sift(I) ;
sift_descr{i} = d
end
Однако VLAD требует, чтобы матрица дескрипторов была 2D. Смотрите здесь. Как правильно обрабатывать дескрипторы SIFT до кодирования VLAD? Спасибо.
1 ответ
Во-первых, вам нужно получить словарь визуальных слов или, если быть более точным, кластеризовать функции SIFT для всех изображений, используя кластеризацию k- средних. В [1] рекомендуется грубая кластеризация с использованием, например, 64 или 256 кластеров.
Для этого нам нужно объединить все дескрипторы в одну матрицу, которую мы затем можем передать vl_kmeans
функция. Далее мы конвертируем дескрипторы из uint8
в single
как vl_kmeans
Функция требует, чтобы вход был либо single
или же double
,
all_descr = single([sift_descr{:}]);
centroids = vl_kmeans(all_descr, 64);
Во-вторых, вы должны создать матрицу назначения, которая имеет измерения NumberOfClusters-by-NumberOfDescriptors, которая назначает каждый дескриптор кластеру. У вас есть большая гибкость в создании этой матрицы назначений: вы можете выполнять мягкие или сложные назначения, вы можете использовать простой поиск ближайших соседей или kd-деревья или другие приблизительные или иерархические схемы ближайших соседей на ваше усмотрение.
В этом уроке они используют kd-деревья, поэтому давайте придерживаться этого: во-первых, необходимо построить kd-дерево. Эта операция принадлежит сразу после нахождения centroids
:
kdtree = vl_kdtreebuild(centroids);
Затем мы готовы построить вектор VLAD для каждого изображения. Таким образом, мы должны снова просмотреть все изображения и независимо рассчитать их вектор VLAD. Сначала мы создаем матрицу назначений в точности так, как описано в руководстве. Затем мы можем кодировать дескрипторы SIFT, используя vl_vlad
функция. Результирующий вектор 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
и создайте вектор VLAD для этого изображения, используя vl_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] Аранджелович Р. и Циссерман А. (2013). Все о ВЛАДЕ. Конференция IEEE по компьютерному зрению и распознаванию образов (CVPR), 1578–1585. https://doi.org/10.1109/CVPR.2013.207