如何在Python中去除信号的常数部分?

0 投票
2 回答
45 浏览
提问于 2025-04-14 16:20

我有一个数据集,其中有些部分是恒定的,偶尔会有一些小的波动。这些恒定的部分可以出现在顶部,也可以在中间。我想把所有恒定的部分去掉,这样数据就能压缩成更小的长度。

比如说,如果有200个连续的数值是相同的(或者在一个可以接受的范围内被认为是恒定的),那么就把这一部分视为恒定。

任何解决方案的代码或逻辑建议都非常欢迎。谢谢你的时间。

我附上了一个样本数据的谷歌云盘链接,格式是.npy。

在下面的示例图片中,我用红色标出了我想要去掉的部分,作为一个例子:

在这里输入图片描述

2 个回答

1

这不是最优雅的解决方案,但它的做法是把一个长度为200的窗口在信号上滑动,观察信号的变化程度。如果变化程度超过某个特定的值,就认为这个信号不是恒定的。可能还有其他方法可以改进这个方案,但我用很少的努力就能去掉很多恒定的部分。

import numpy as np
import matplotlib.pyplot as plt

x = np.load(r"C:\Users\ryansenne\Downloads\sample.npy")

# Detects constant sections and removes them
def remove_constant_sections(signal, window_size=200, threshold=0.01):
    filtered_signal = []
    i = 0
    while i < len(signal) - window_size:
        window = signal[i:i+window_size]
        if np.var(window) > threshold:
            filtered_signal.extend(window)
            i += window_size
        else:
            i += 1
    # Add the remaining values that may not fit into a full window
    filtered_signal.extend(signal[i:])
    return np.array(filtered_signal)


filtered_signal = remove_constant_sections(x)

enter image description here

0

我想出了以下的解决方案。@rsenne 的回答帮我入门,但那并不是我想要的解决方案。如果你觉得我的方案还有什么可以改进的地方,请告诉我,这样可以提高性能。

import numpy as np

def remove_flat_segments(data, threshold, min_length):
       
       """
       Remove flat segments from data within a threshold and with a minimum length.
    
       Parameters:
        data (ndarray): Input data array.
        threshold (float): Threshold for flatness.
        min_length (int): Minimum length of flat segment to be removed.
    
       Returns:
        ndarray: Data with flat segments removed.
       """
    flat_segments = []
    start_idx = None
    
    for i in range(len(data)):
        if start_idx is None:
            start_idx = i
        elif abs(data[i] - data[i-1]) > threshold:
            if i - start_idx >= min_length:
                flat_segments.append((start_idx, i-1))
            start_idx = None
    
    if start_idx is not None and len(data) - start_idx >= min_length:
        flat_segments.append((start_idx, len(data)-1))
    
    if len(flat_segments) > 0:
        flat_indices = np.concatenate([np.arange(start, end+1) for start, end in flat_segments])
        return np.delete(data, flat_indices)
    else:
        return data


threshold = 0.01
min_length = 1000

filtered_data = remove_flat_segments(data, threshold, min_length)

生成的图像看起来是这样的:

在这里输入图像描述

撰写回答