获得一维数据的峰值(C++/Matlab)

本方法源自于求解图像功率谱中某列(一维离散数据)的峰值之间的距离问题。比如输入的一维离散数据的分布如下:

即从左到右,分别代表下标从1到n(c/python中为0到n-1)的数值大小,间隔为1,n表示输入一位数据的长度。在此对数据的峰重新定义:满足左右值都比它小的等值区间,比如[1,2,2,1]的[2,2]、[1,2,0]的[2]都是数据的“峰”,但[1,2,2,4]、[1,2,2,2]不存在峰。所有峰中最高的峰称作“主峰”,其他为“次峰”。对于以上的例子,所有峰已手动圈出。

如图所示,共18个峰。现在问题是,输入一组数据,怎么求得所有的峰的值(或者坐标)呢?(坐标用中点表示区间)

在这以坐标为例,每个峰的坐标由它所在区间的中点表示。

首先在这里定义两个变量:start_peak和end_peak。分别动态表示每个峰的区间开始和结束的坐标。

遍历一维数据,如果当前数据的值大于上一个(左侧)数据的值,说明位于上升过程,更新start_peak为当前值的下标;如果小于,(并且start_peak的值不是初始化值),说明上一个数据的下标已经是该峰的区间结束坐标,更新end_peak为上一个值的下标,这样就得到了这个峰的开始和结束两个坐标,所以在更新之后紧接着将start_peak和end_peak的平均值保存在结果中,同时start_peak归为初始化值(防止下降过程中每次都会保存一个峰,和上一段粗体呼应)。最后遍历结束返回即可。其他峰值或区间等同理稍微修改就能够获得。

matlab版代码:

function peak_index=find_peak(data)
    n=length(data);%数据长度
    start_peak=0;%初始化
    end_peak=0;
    t=0;
    for i=1:n
        if (i>=2 && data(i)>data(i-1))
            start_peak=i;
        end
        if (i>=2 && data(i)<data(i-1)&&start_peak)
            end_peak=i-1;
            t=t+1;
            peak_index(t)=(start_peak+end_peak)/2;
            start_peak=0;     %初始化  
        end
    end
end

c++版:(没有跑过,纯直接翻译)

扫描二维码关注公众号,回复: 13016140 查看本文章
    vector<int> find_peak(vector<int>& data) {
        vector<int> ans;
        int n=data.size();
        int start_peak=-1;
        int end_peak=-1;
        for(int i=0;i<n;i++){
            if(i>=1 && data[i]>data[i-1])
                start_peak=i;
            if(i>=1 && data[i]<data[i-1]&& start_peak>=0){
                end_peak=i-1;
                ans.push_back(ceil((end_peak+start_peak)/2));
                start_peak=-1;
            }
        }
    return ans; 
    }

最后的返回的结果:

经过对比后,和图片一致。

猜你喜欢

转载自blog.csdn.net/qq_36614557/article/details/109657803