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

时间:2016-10-18 22:24:33

标签: matlab detection

我正在测试具有不同线宽和背景的FileExchange项目FindPeaksFast的有效性。 测试1成功,该工具检测从1px到10px的所有峰值。 然而,当测试在对象图的帧(即灰色背景上的对象(图))上找到峰值时,测试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]); % http://stackoverflow.com/a/15529630/54964
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节输出错误,因为不知道如何在频谱图上应用该功能

enter image description here enter image description here enter image description here enter image description here

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
操作系统:Debian 8.5

1 个答案:

答案 0 :(得分:1)

您没有正确使用此功能。

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

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);

enter image description here

即使您拥有的只是单个像素,也不是该功能应该具有的功能,因为据说峰值点扩散函数需要大于某些像素数,并且它们被认为是疏。该函数对样本图像进行了演示,工作正常。

此外,完全不清楚你在这里的峰值甚至意味着什么。

编辑:

以下是如何使用该功能的示例。首先让我们选择我们“创造”峰值的随机位置:

I=rand(200)>0.9995;

这使得二元矩阵仅选择大于0.9995的点(或具有值1)。在每一步,您都可以imagesc(I)查看I的外观。

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

I=I*100;

这很重要,因为牙列的峰值需要是其附近的最大值。在现实生活中,峰值大多不是单个像素,它们有一些“宽度”或扩散(这也是它所处理的功能):

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

这里,这种传播是通过某个宽度的高斯的“点扩散函数”完成的。

让我们添加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+')

enter image description here

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