匹配胡须的轨迹

时间:2015-07-16 12:02:42

标签: image matlab cluster-analysis

我正在进行胡须跟踪实验。我有高速视频(500fps)的老鼠拂过物体。在每个这样的视频中,我追踪了老鼠的鼻子和胡须的形状。由于跟踪噪声很大,每帧中的胡须数量可能会有所不同(请参见附图中的2个连续帧,注意左侧帧中出现的黄色假阳性晶须,而不是右侧帧中出现的黄色假阳性晶须)。

参见示例1:enter image description here

作为跟踪的最终结果,对于每个帧,我得到不同数量的可变长度向量;每个矢量对应一个晶须。此时我想匹配帧之间的胡须。我已经尝试使用Matlab的样本对齐来做到这一点,但它只能在某种程度上正常工作。其结果如下(在附图中显示了超过227帧的所有晶须的基点)。

参见示例2:enter image description here

我想运行一些算法来正确地聚集晶须,这样每个晶须在很多帧的过程中被识别为自身并与其他晶须分离。换句话说,我希望第二个图像中的每个略微正弦的轨迹被识别为一个轨迹。无论我使用什么排序算法都应该考虑到胡须可能会消失并在连续帧之间重新出现。不幸的是,我完全没有想法......

任何帮助?

再一次,请记住,对于附加图像2中的每个点,我有许多数据点,因为这只是一个胡须基点的图,而实际上我有整个胡须长度的数据。

1 个答案:

答案 0 :(得分:0)

这就是我处理问题的方法。假设不同大小的数据向量是cell类型,称为dataVectors,并且知道胡须的数量(nSignals),我会尝试将数据扩展到从原始数据,然后在两个维度上执行k-means。

所以,首先我会得到矢量的最大大小,以便将数据转换为矩阵并进行NaN - 填充。

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

现在,我会通过将数据提升到两个(或三个,您的选择)来生成数据。这只是一个非常简单的转变。但是你可以在这里使用kernel methods并将每个向量投射到其余的向量;但是,我不认为这是必要的,如果你的数据真的很大,那么效率可能会很低。现在,将数据提升到2的幂应该可以解决问题。结果存储在第二维中。

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将在行1和列1中,第一个胡须的原始数据(或我在此处称之为信号)和列{{1}将有新的维度。我们假设您总共有2个胡须,8将会有projData1,{{1}行中第一个胡须的数据}}, 等等。行9172中的第二个胡须的数据,等等。如果您想回到原始数据,那么这很重要。此外,您可以尝试不同的10,但我怀疑它会产生很大的不同。

现在我们对2D数据执行k-means;但是,我们提供了初始点而不是让它用k-means ++来确定它们。正如我在此提出的,初始点是每个晶须的每个矢量的第一个数据点。以这种方式,k-means将离开那里并相应地移动到集群装置。我们将结果保存在18

projDegree

你有它。变量idxK将告诉您哪个数据点属于哪个群集。

以下是我提出的解决方案的工作示例。第一部分只是尝试生成看起来像您的数据的数据,您可以跳过它。

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

enter image description here

idxK

enter image description here

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

如果有帮助,请告诉我。