从线轮廓识别峰值

时间:2017-01-18 08:31:50

标签: dm-script

我想询问是否可以在DM上找到强度曲线的每个最大值和最小值的位置。

如何在下面的示例中提出一个识别峰值位置的简单脚本?

以下是沿Y方向的STEM图像的线强度分布的屏幕截图:

Screenshot of line intensity profile of a STEM image along the Y-direction

2 个答案:

答案 0 :(得分:1)

如果要过滤“严格”局部最大值,则可以使用图像表达式和条件“叔”运算符轻松完成此操作。以下示例说明了这一点:

image CreateTestSpec( number nChannels, number nPeaks, number amp, number back )
{
    image testImg := RealImage( "TestSpec", 4, nChannels )
    testImg = amp * cos( PI() +  2*PI() * nPeaks * icol/(iwidth-1) )
    testImg += back
    testImg = PoissonRandom( testImg )
    return testImg
}

image FilterLocalMaxima1D( image spectrumIn, number range )
{
    image spectrumOut := spectrumIn.ImageClone()
    for( number dx = -range; dx<=range; dx++  )
        spectrumout *= ( spectrumIn >= offset(spectrumIn,dx,0) ? 1 : 0 )

    spectrumout.SetName("Local maxima ("+range+") filtered")
    return spectrumOut
}

image test1 := CreateTestSpec(256,10,1000,5000)
image test2 := FilterLocalMaxima1D(test1,3)
test1.ShowImage()
test2.ShowImage()

但是,考虑到噪音(也在您的示例图像中),您可能希望围绕这些“局部最大值”执行拟合,以确保您真正得到您想要的效果。上面的数据只是其中的起点。

此外:有时您可以先对数据进行平均,然后找到局部最大值,而不是在每个峰值中进行实际数据拟合。如果您“很好地”了解真实峰值的宽度,这尤其适用。

这就是例子:

image CreateTestSpec( number nChannels, number nPeaks, number amp, number back )
{
    image testImg := RealImage( "TestSpec", 4, nChannels )
    testImg = amp * cos( PI() +  2*PI() * nPeaks * icol/(iwidth-1) )
    testImg += back
    testImg = PoissonRandom( testImg )
    return testImg
}

image FilterLocalMaxima1D( image spectrumIn, number range )
{
    image spectrumOut := spectrumIn.ImageClone()
    for( number dx = -range; dx<=range; dx++  )
        spectrumout *= ( spectrumIn >= offset(spectrumIn,dx,0) ? 1 : 0 )

    spectrumout.SetName("Local maxima ("+range+") filtered")
    return spectrumOut
}

image FilterLocalMaxima1DAveraged( image spectrumIn, number range )
{
    image avSpectrum := spectrumIn.ImageClone()
    avSpectrum = 0
    for( number dx = -range; dx<=range; dx++  )
        avSpectrum += offset(spectrumIn,dx,0) 
    avSpectrum *= 1/(2*range+1)

    image spectrumOut := spectrumIn.ImageClone()
    for( number dx = -range; dx<=range; dx++  )
        spectrumout *= ( avSpectrum >= offset(avSpectrum,dx,0) ? 1 : 0 )

    spectrumout.SetName("Local maxima ("+range+") filtered, average")
    return spectrumOut
}

image test1 := CreateTestSpec(256,10,1000,5000)
image maxPeaks      := FilterLocalMaxima1D(test1,3)
image maxPeaksAv    := FilterLocalMaxima1DAveraged(test1,3)
test1.ShowImage()
test1.ImageGetImageDisplay(0).ImageDisplayAddImage( maxPeaks, "local max" )
test1.ImageGetImageDisplay(0).ImageDisplayAddImage( maxPeaksAv, "local max from Average" )

test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 0, 1, 0.7, 0.7, 0.7 )

test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceDrawingStyle( 1, 2)
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 1, 1, 1, 0, 0 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceTransparency( 1, 1, 0.7 )

test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceDrawingStyle( 2, 2)
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceComponentColor( 2, 1, 0, 1, 0 )
test1.ImageGetImageDisplay(0).LinePlotImageDisplaySetSliceTransparency( 2, 1, 0.7 )

答案 1 :(得分:0)

最简单的方法是使用1点(或2点)邻域来判断中心是否为最小值(最大值)。请参阅下面的伪代码:

// assume 0 <= x <= maxX, y(x) is value at point x, radius is 1
x = 1;

while (x + 1 <= maxX)
{
    if (y(x) > y(x-1) and y(x) > y(x+1))
        // we found a maximum at x

    if (y(x) < y(x-1) and y(x) < y(x+1))
        // we found a minimum at x

    x = x + 1
}

对于2点邻域,最大条件可以是

if (y(x) > y(x-1) and y(x-1) >= y(x-2) and y(x) > y(x+1) and y(x+1) >= y(x+2))

注意&gt; =这里。你可以使用&gt;代替。

注意,如果两个连续的x具有相同的值y,则上述方法将找不到最大值。对于y(0)= 0,y(1)= 1,y(2)= 1,y(3)= 0,对于x = 1,x = 2也不会找到最大值。