2015-07-16 4 views
2

Я выполняю эксперименты по отслеживанию усов. У меня есть высокоскоростные видеоролики (500 кадров в секунду) крыс, размахивающих против объектов. В каждом таком видео я отслеживал форму рыла и усов крысы. Поскольку отслеживание является шумным, количество усов в каждом кадре может быть другим (см. 2 последовательных кадра в прикрепленном изображении, обратите внимание на желтый ложноположительный бакенбард, появляющийся в левом фрейме, но не правильный).Соответствующие траектории усов

Смотри пример 1: enter image description here

В качестве конечного результата слежения, я получаю, для каждого кадра, различным количеством векторов переменной длины; каждый вектор, соответствующий одному нитевому уксусу. В этот момент я хотел бы совместить бакенбарды между кадрами. Я попытался использовать совпадение образца Matlab для этого, но он работает только несколько правильно. Его результаты приведены ниже (в прилагаемом изображении, показывающем базовую точку всех усов более 227 кадров).

пример 2: enter image description here

Я хотел бы запустить некоторый алгоритм правильно группироваться бакенбарды, так что каждый усов признается сама и отделена от других в течение многих кадров. Другими словами, я бы хотел, чтобы каждая слегка синусоидальная траектория во втором изображении была признана одной траекторией. Независимо от того, какой алгоритм сортировки я использую, следует учитывать, что усы могут исчезнуть и снова появиться между последовательными кадрами. К сожалению, у меня все идеи ...

Любая помощь?

Еще раз помните, что для каждой точки в прикрепленном изображении 2 у меня много точек данных, так как это всего лишь график базовой точки вискера, а на самом деле у меня есть данные для всей длины усов.

+0

После просмотра рисунка в изображении 2 я бы предложил вам преобразовать данные в более высокое измерение, возможное 2D или 3D, используя, например, методы ядра, и выполнить «k-means» в этом более высоком измерении. Мне кажется, что полиномиальное ядро ​​степени 2 или 3 должно сделать трюк. И если вы знаете, сколько усов вы ищете, тогда сделайте так, чтобы ваш 'k' в' k-mean'. Если вы предоставите некоторые примеры данных, я могу написать для вас рабочее решение. Дайте мне знать, если это имеет смысл. –

ответ

0

Вот как я могу решить проблему. Предполагая, что векторы данных разного размера имеют тип cell, называемый dataVectors, и, зная количество усов (nSignals), я попытался бы распространить данные на второе измерение, полученное из исходных данных, а затем выполнить k-средние по двум измерениям ,

Итак, сначала я бы получил максимальный размер векторов, чтобы преобразовать данные в матрицу и сделать NaN -padding.

maxSize = -Inf; 
for k = 1:nSignals 
    if length(dataVectors{k}.data) > maxSize 
     maxSize = length(dataVectors{k}.data); 
    end 
end 

Теперь я хотел бы сделать 2D данных путем повышения его мощности двух (или трех, ваш выбор). Это просто очень простая трансформация. Но вы могли бы использовать здесь kernel methods и проектировать каждый вектор против остальных; однако я не думаю, что это необходимо, и если ваши данные действительно большие, это может быть неэффективным. Пока, повышение данных до уровня двух должно сделать трюк. Результат сохраняется во втором измерении.

projDegree = 2; 
projData = zeros(nSignals, maxSize, 2).*NaN; 
for k = 1:nSignals 
    vecSize = length(dataVectors{k}.data); 
    projData(k, 1:vecSize, 1) = dataVectors{k}.data; 
    projData(k, 1:vecSize, 2) = dataVectors{k}.data.*projDegree; 
end 
projData = reshape(projData, [], 2); 

Здесь projData будут иметь в строке и столбце 11 исходные данные первого уса (или сигнала, как я называть его здесь), и столбец 2 будет иметь новое измерение. Предположим, что у вас есть 8 бакенбардов, тогда projData будет иметь данные первого вискера в ряду 1, 9, 17 и так далее. Данные второго низа в ряду 2, 10, 18 и т. Д. Это важно, если вы хотите вернуться к исходным данным. Кроме того, вы можете попробовать с различными projDegree с, но я сомневаюсь, что это будет иметь большое значение.

Теперь мы выполняем k-means по 2D-данным; однако мы предоставляем исходные точки вместо того, чтобы позволить им определять их с помощью k-средств ++. Начальные точки, как я предлагаю здесь, являются первой точкой данных каждого вектора для каждого уса. Таким образом, k-средства отступят оттуда и соответственно перейдут к кластерам. Мы сохраняем результаты в idxK.

idxK = kmeans(projData,nSignals, 'Start', projData(1:nSignals, :)); 

И вот оно у вас есть. Переменная idxK сообщит вам, какая точка данных принадлежит кластеру.

Ниже приводится рабочий пример из предложенного мной решения. Первая часть просто пытается создать данные, которые выглядят как ваши данные, вы можете пропустить их.

rng(9, 'twister') 
nSignals = 8; % number of whiskers 
n = 1000;  % number of data points 
allData = zeros(nSignals, n); % all the data will be stored here 

% this loop will just generate some data that looks like yours 
for k = 1:nSignals 
    x = sort(rand(1,n)); 
    nPeriods = round(rand*9)+1;  % the sin can have between 1-10 periods 
    nShiftAmount = round(randn*30);  % shift between ~ -100 to +100 
    y = sin(x*2*pi*nPeriods) + (randn(1,n).*0.5); 
    y = y + nShiftAmount; 
    allData(k, :) = y; 
end 
nanIdx = round(rand(1, round(n*0.05)*nSignals).*((n*nSignals)-1))+1; 
allData(nanIdx) = NaN;  % about 5% of the data is now missing 

figure(1); 
for k = 1:nSignals 
    nanIdx = ~isnan(allData(k, :)); 
    dataVectors{k}.data = allData(k, nanIdx); 
    plot(dataVectors{k}.data, 'kx'), hold on; 
end 

enter image description here

% determine the max size 
maxSize = -Inf; 
for k = 1:nSignals 
    if length(dataVectors{k}.data) > maxSize 
     maxSize = length(dataVectors{k}.data); 
    end 
end 

% making the data now into two dimensions and NaN pad 
projDegree = 2; 
projData = zeros(nSignals, maxSize, 2).*NaN; 
for k = 1:nSignals 
    vecSize = length(dataVectors{k}.data); 
    projData(k, 1:vecSize, 1) = dataVectors{k}.data; 
    projData(k, 1:vecSize, 2) = dataVectors{k}.data.*projDegree; 
end 
projData = reshape(projData, [], 2); 
figure(2); plot(projData(:,1), projData(:,2), 'kx'); 

enter image description here

% run k-means using the first points of all measure as the initial points 
idxK = kmeans(projData,nSignals, 'Start', projData(1:nSignals, :)); 
figure(3); 
liColors = [{'yx'},{'mx'},{'cx'},{'bx'},{'kx'},{'gx'},{'rx'},{'gd'}]; 
for k = 1:nSignals 
    plot(projData(idxK==k,1), projData(idxK==k,2), liColors{k}), hold on; 
end 

enter image description here

% plot results on original data 
figure(4); 
for k = 1:nSignals 
    plot(projData(idxK==k,1), liColors{k}), hold on; 
end 

enter image description here

Сообщите мне, если это поможет.

Смежные вопросы