matlab - 调整 matlab/octave 信号中发现的峰值 - 速度问题

标签 matlab octave vectorization

我有一个函数可以根据信号的其余部分查找并调整峰值。我遇到的问题是,如果信号有 8000 点,那么它工作得很好,速度非常快,大约 1 分钟内完成,但如果信号有 200000 点,则需要一个多小时。有什么想法可以加快这个功能吗?

%example [peaks_found,peak_sig_adj]= rtadjpeak (signal, 3,3)
function [peaks_found,peak_sig_adj] =rtadjpeak (signal, T_multi_lower, T_multi_upper)

    Af=signal;

    % Thresholds
    T_lower = -mean(abs(signal))*T_multi_lower
    T_upper =mean(abs(signal))*T_multi_upper


    % initialisation
    [peaks_r,peaks_c] = find( Af < T_lower | Af > T_upper);
    peaks = find( Af < T_lower | Af > T_upper);
    %find the mean of all the peaks

    counter = 0;

    while ~isempty(peaks)
            peaks = find( Af < T_lower | Af > T_upper);
            try
                    Af(peaks) = ( Af(peaks-1) + Af(peaks+1) ) / 2;
            catch
                    if peaks(1) == 1
                            Af(1) = 0;
                    else
                            Af(end) = 0;
                    end
            end   
            counter=counter+1;
    end
    peaks_found=counter
    peak_sig_adj=Af;
end

PS:我使用的是 Octave 3.8.1

我按照某人推荐的方式做了分析器,但我仍然不知道如何提高此功能的速度

profile on;
rtadjpeak(z_sig_combined_L1, 3, 3);
profile off;

>>>T_lower = -0.50551
>>>T_upper =  0.50551
>>>peaks_found =  1013

profshow (profile ("info"));

   #  Function Attr     Time (s)        Calls
---------------------------------------------
  14      find             0.043         1017
   5  binary <             0.023         1017
   1 rtadjpeak             0.023            1
   6  binary >             0.022         1019
  20  binary |             0.018         1015
  23  binary +             0.002         3036
  22  binary -             0.002         1013
  17  binary /             0.001         1013
  21   isempty             0.000         1014
   8  prefix !             0.000         1016
   2       abs             0.000            2
   3      mean             0.000            2
  16       sum             0.000            2
  25   profile             0.000            1
   9     false             0.000            3
   4    nargin             0.000            7
  13      size             0.000            2
   7 isnumeric             0.000            2
  10 binary ==             0.000            4
  11      true             0.000            2

最佳答案

我认为连续调用 find 来查找最多 200000 个元素的逻辑数组有点浪费资源。这是一个实现(在 MATLAB 中测试),即使使用循环,它也应该比原始版本快得多:它只传递值数组一次 查找调用,并动态调整峰值:

    function [peaks_found,peak_sig_adj] =rtadjpeak_fast (signal, T_multi_lower, T_multi_upper)

            %// Thresholds
            T_lower = - mean(abs(signal))*T_multi_lower;
            T_upper =   mean(abs(signal))*T_multi_upper;

            %// Initial conditioning for signal
            Af = signal;

            if Af(1) > T_upper
                    Af(1) = T_upper;
            elseif Af(1) < T_lower
                    Af(1) = T_lower;
            end;
            if Af(end) > T_upper
                    Af(end) = T_upper;
            elseif Af(end) < T_lower
                    Af(end) = T_lower;
            end;

            %// Logical array of peaks
            peaks = (Af < T_lower) | (Af > T_upper);

            %// Find continuous peaks, in signal and replace values with average in
            %// the normal range.
            n_max   = numel(peaks);
            in_peak = false;
            counter = 0;
            for k = 1:n_max
                    if ~in_peak && (peaks(k))
                            % Begin of peak
                            n_begin = k;
                            in_peak = true;

                    elseif in_peak && ~(peaks(k))
                            % End of peak, a sample ago
                            n_end   = k-1;
                            in_peak = false;
                            counter = counter + 1;

                            % Calculate average in between
                            n_length = n_end - n_begin + 1;
                            Af_span  = Af(n_end+1) - Af(n_begin-1);
                            Af(n_begin:n_end) = ...
                                  Af(n_begin-1) ...
                                + (Af_span / (n_length + 1)) * (1:n_length);
                    end;
            end;

            %// Set output
            peaks_found  = counter;
            peak_sig_adj = Af;
    end

请注意,%// 只是一个在 StackOverflow 代码格式化程序上正确显示注释的技巧。否则我会使用普通的注释 %.

关于matlab - 调整 matlab/octave 信号中发现的峰值 - 速度问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26239239/

相关文章:

matlab - 更改快速傅里叶逆变换 (ifft) 以使用任意波形而不是正弦波来创建新信号

python - Numpy:在各种索引的矩阵行中插入任意数量的零

matlab - 词袋训练和测试opencv,matlab

matlab - 马特沃特,巴特沃思

matlab - 通过与另一个数组进行比较来查找数组中的元素

octave - Octave符号包中的分段函数?

r - 在R中快速生成数字序列的方法

r - 在 R 中对以函数作为参数的函数进行积分

arrays - 使用之字形排序将 1d 矩阵转换为 2d 矩阵

matlab - 在 MATLAB 中获取当前图形大小