信号压缩矢量化,python源代码

自变量 n 控制点的数量,因变量误差 log10(loss) 

压缩和解压效果图,绿线为原始信号,蓝点为压缩后的控制点,红线为解压出来的信号

源代码:

import numpy as np
from matplotlib import pyplot as plt


def init_N(n, k, X, T):
    """
    生成初始化的参数矩阵
    :param n: 控制点数量,int
    :param k: 基函数的阶数,int, 默认为2,建议2,3,4,最小为2,越大越平滑,越大速度越慢
    :param X: 自变量矩阵,取值范围[0,1] (shape=[sample], dtype=float)
    :param T: 控制点系数矩阵,取值范围[0,1] (shape=[n + k + 1], dtype=float)
    :return N:  (shape=[sample, n], dtype=float)
    """ 
    X = X[None]   # shape=[1, sample]
    T = T[:, None]# shape=[n+k+1, 1]
    m = n + k + 1
    N = 1 * (T[:-1] <= X) * (X < T[1:])  # shape=[n+k+1, sample]
    for k in range(1, k + 1):  # 动态规划 k ∈ [1, k]
        n = m - k - 1  # 每次更新的控制点数量
        c1 = T[k:n + k] - T[:n]
        c2 = T[k + 1:n + k + 1] - T[1:n + 1,]
        c1[c1 == 0] = 1
        c2[c2 == 0] = 1
        w1 = (X - T[:n]) / c1
        w2 = (T[k + 1:n + k + 1] - X) / c2
        N = N[:-1] * w1 + N[1:] * w2
    N = N[:n].T # 截取前n个,然后交换行列
    return N  # sample, n


def init_T_X(k, m, sample):
    """
    生成初始化的参数向量
    :param k: 基函数的阶数,int, 默认为2,建议2,3,4,最小为2,越大越平滑,越大速度越慢
    :param m: 系数矩阵的长度,int,m=n+k+1
    :param sample: 采样点数量, int
    :return T: 系数矩阵,取值范围[0,1] (shape[n + k + 1], dtype=float)
    :return X: 自变量矩阵,取值范围[0,1] (shape=[sample], dtype=float)
    """
    # clame 模式
    T = np.concatenate([
        np.zeros(k),
        np.linspace(0, 1, m - 2 * k),
        np.ones(k)]
    )
    gama = 1e-9
    first = T[k]
    last = T[-k - 1] * (1 - gama) + gama * T[-k - 2]
    X = np.linspace(first, last, sample)
    return T, X


def unzip(P, k, sample):
    """
    解压点,生成曲线
    :param P: 控制点矩阵,(shape=[n], dtype=float)
    :param k: 基函数的阶数,int, 默认为2,建议2,3,4,最小为2,越大越平滑,越大速度越慢
    :param sample: 采样点数量, int
    :return data: 解压后的曲线,(shape=[sample], dtype=float)
    """
    n = len(P)
    T, X = init_T_X(k=k, m=k + n + 1, sample=sample)
    N = init_N(n=n, k=k, T=T, X=X)
    numerator = np.sum(P[None] * N, axis=-1)
    denominator = np.sum(N, axis=-1)
    data = numerator / denominator
    return data


def zip(data, n, k):
    """
    压缩曲线,生成控制点矩阵
    :param data: 曲线上的采样点,(shape=[sample], dtype=float)
    :param n: 控制点的数量,int
    :param k: 曲线的阶数,int
    :return P: 控制点矩阵, (shape=[n], dtype=float)
    """
    T, X = init_T_X(k=k, m=k + n + 1, sample=sample)
    N = init_N(n=n, k=k, T=T, X=X)
    # print(N)
    a = N  # r 行 c列, 其中 r 代表采样点数量,c 代表控制点数量
    b = data * np.sum(N, axis=-1)  # r 行
    P = np.linalg.lstsq(a, b, rcond=None)
    # print(P)
    return P[0],P[1]


if __name__ == "__main__":
    sample = 720 # 采样数量
    X = np.linspace(0, 1, sample)
    Y = np.sin(7 * np.pi * X + 6) * (0.2 + np.abs(X - 0.8)) + \
        np.sin(9 * np.pi * X + 9) * (0.2 + np.abs(X - 0.1))  + \
        np.sin(32 * np.pi * X + 1) * (0.2 + np.abs(X - 0.6))         #  np.sin(17 * np.pi * X + 1) * (0.2 + np.abs(X - 0.1)) + \

    k = 2 # 阶数
    
    y_loss = []
    x_loss = list(range(36,128))
    for n in x_loss:
        P,loss = zip(Y, n, k) # 压缩提取控制点矩阵
        y_loss.append( np.log10(loss))
    plt.plot(x_loss, y_loss, 'g-', marker='+', label='') 
    plt.show()
    n = 32*2 + 2
    P,loss = zip(Y, n, k) # 压缩提取控制点矩阵

    unzip_Y = unzip(P, k, sample) # 解压 

    plt.plot(X, Y, 'g-', marker='+', label='origin line')
    plt.plot(np.linspace(0, 1, n), P, 'bo-.', label='zip point')
    plt.plot(X, unzip_Y, 'r-', marker='+', label='unzip line')

    plt.legend()
    plt.show()
  • 9
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值