如何使用 Matlab FastPeakFind 检测灰色背景上的峰?

How to detect peaks on gray background with Matlab FastPeakFind?

我正在测试具有不同线宽和背景的 FileExchange 项目 FindPeaksFast 的有效性。 测试 1 成功,该工具检测到从 1 像素到 10 像素的所有峰值。 然而,当测试在对象图的框架上找到峰值时,测试 2 失败,即灰色背景上的对象(图)。 该工具在白色背景上运行良好。 代码

close all; clear all; clc;

f = figure; 
hax = axes(f); 
% Comment this out for Test 2
%zeroFigureDecorations(hax); 

af = figure('Name', 'Do Not Touch');

x = rand(1,100);
y = rand(1,100);
linewidth=1; 
plot(hax, x,y, 'LineWidth', linewidth); 

I = getframe(hax); 
I = I.cdata; 

% https://se.mathworks.com/matlabcentral/fileexchange/37388-fast-2d-peak-finder
p=FastPeakFind(I);
% Input: 344x435x3 uint8

hold(hax, 'on'); 
plot(hax, p(1:2:end),p(2:2:end),'r+')
hold(hax, 'off'); 

function zeroFigureDecorations(ax)
axis(ax, 'tight');
set(ax, 'yTickLabel', []);
set(ax, 'xTickLabel', []);
set(ax, 'Ticklength', [0 0]); % 
colormap(ax, 1-gray(1024));
box(ax, 'off');
axis(ax, 'off');
end

输出如下,图1显示当背景为白色时,该函数可以检测到线条上的东西,但不能检测到正确的位置。

Linewidth Output  
10        166x1 double 
1         844x1 double 

Table: full axis decoration in Test 1

Linewidth Output
10        []
1         [] 

Table: no axis decorations, after zeroFigureDecorations(hax) in Test 2

图1 行作为输入(参见 Bla 的回答)及其输出, 图 2 第 2 节输出错误, 图 3 另一个不能应用于简单曲线函数的例子, 图 4 第 3 节输出错误,因为不知道如何在频谱图上应用该函数

2 使用 bla 的示例数据进行测试

f0 = figure; 
hax0 = axes(f0); 
d=uint16(conv2(reshape(single( 2^14*(rand(1,128*128)>0.9995) ),[128 128]) ,fspecial('gaussian', 10,2),'same')+2^4*rand(128)); 
imagesc(d, 'Parent', hax0);

I = getframe(hax0); 
I = I.cdata; 
p=FastPeakFind(I);
hold(hax0, 'on'); 
plot(hax0, p(1:2:end),p(2:2:end),'r+')
hold(hax0, 'off'); 

图2输出错误

3 使用频谱图进行测试

f3 = figure; 
hax3 = axes(f3); 
N = 1024*10;
n = 0:N-1;

w0 = 2*pi/5;
x = sin(w0*n)+10*sin(2*w0*n);

s = spectrogram(x);
spectrogram(x,'yaxis')

p=FastPeakFind(s);
hold  on; 
plot(p(1:2:end),p(2:2:end),'r+')

Matlab: 2016b
OS:Debian 8.5

您没有正确使用该功能。

您的代码是这样的(逐字):

f = figure; 
hax = axes(f); 
af = figure('Name', 'Do Not Touch');

x = rand(1,100);
y = rand(1,100);
linewidth=1; 
plot(hax, x,y, 'LineWidth', linewidth); 

I = getframe(hax); 
I = I.cdata; 

矩阵 I 不是像函数预期那样包含峰值的矩阵。这是它的样子:

imagesc(I);

即使您只有单个像素,这也不是函数应该具有的,因为据说峰值点扩散函数需要大于一些像素,并且假设它们稀疏。该函数在示例图像上进行了演示,效果很好。

此外,完全不清楚您在这里所说的峰值是什么意思。

编辑:

下面是如何使用该函数的示例。首先让我们 select 随机位置 "create" 峰值:

I=rand(200)>0.9995;

这将生成一个二进制矩阵,其中只有大于 0.9995 selected(或值为 1)的点。在每个步骤中,您都可以 imagesc(I) 查看 I 的外观。

在现实生活中,相机在这些点上会有一些强度,所以我们写:

I=I*100;

这很重要,因为牙列的峰值需要是其附近的最大值。在现实生活中,峰值大多不是单个像素,它们有一些 "width" 或扩散(这也是函数所说的它处理的内容):

I=conv2(I,fspecial('gaussian',10,2),'same');

这里,这个传播是由一个 "point-spread function" 一些宽度的高斯完成的。

让我们添加一些 30% 的噪声(请注意,在最后一步之后,峰值的最大值不再是 100,因为它也扩散到其他像素):

I=I+0.3*max(I(:))*rand(size(I));

让我们找到峰值

 p=FastPeakFind(I);

看看效果如何:

subplot(1,2,1);imagesc(I); 

subplot(1,2,2);imagesc(I); hold on
plot(p(1:2:end),p(2:2:end),'r+')

在函数代码中,示例是在一行中执行我在此处编写的内容。请注意,有一个 edg 参数,因为这不适用于图像边缘的峰值。我认为可以通过用零填充图像来解决这辆出租车...