检测PPG信号的心跳

news2024/11/26 14:58:25

基于大佬的代码。

PPG信号靠心率 (HR) 进行估计,主要取决于收缩压峰值检测的准确性。与 ECG 不同,PPG 信号形式简单和特定点 少。低振幅 PPG 信号更容易受到噪声污染和其他不良影响的影响,例如baseline drift和wandering。这是由于信号强度与噪声功率相当。在这种情况下,PPG 记录可能会出现一些波纹,如果检测算法不够robust,这些波纹可能会被错误地标记为峰值。
有人认为应该从信号采集和调节阶段解决 PPG 波幅度的降低问题,但这种降低也可以在受伤后(例如,当患者经历手术过程的第一个手术切口时)或呼吸暂停期间观察到,作为交感神经张力增加引起的外周血管收缩的结果。

PPG(Photoplethysmography)光电容积脉搏波描记法

导入数据后,用signal.butter创建butterband过滤器

# Specify cutoff in Hertz
lpf_cutoff = 0.7 
hpf_cutoff = 10

#Create a Butterworth filter
sos_ppg = signal.butter(10,
                    [lpf_cutoff, hpf_cutoff],
                    btype = 'bp',
                    analog = False,
                    output = 'sos',
                    fs = segment_data.fs)

w, h = signal.sosfreqz(sos_ppg,
                   2000,
                   fs = fs)

过滤出的信号和原信号一起塞进sosfiltfilt获得过滤之后的信号

ppg_filt = signal.sosfiltfilt(sos_ppg, ppg)

可视化比较一下:
在这里插入图片描述

对信号求导

# Calculate first derivative
d1ppg = signal.savgol_filter(ppg_filt, 9, 5, deriv=1)

# Calculate second derivative
d2ppg = signal.savgol_filter(d1ppg, 9, 5, deriv=1)

对于PPG信号,这篇文章<Analysis on Four Derivative Waveforms of Photoplethysmogram (PPG) for Fiducial Point Detection>里说
可以对PPG信号求导,一阶导数 PPG (VPG) 和二阶导数 PPG (APG) 对应的分别是velocity plethysmogram 和acceleration plethysmogram。PPG信号的峰值对病理的研究很重要,导数波形能表现出更多的重要波峰。

光电体积描记图波形带有四个主要基准点,即起始点(脚)、收缩峰、重搏切迹和舒张峰。这显示在下图,表示收缩期脉搏的开始,此时含氧血液在测量部位流动。收缩期峰值是收缩期射血开始后的最大峰值。从开始到收缩的上升沿表示动脉中压力的增加,如动脉血压 (ABP) 波形中所测量的那样。重搏切迹和舒张峰是外周的波反射,受动脉硬度或血管阻力和顺应性的影响 。如果发作与收缩期射血的开始有关,那么舒张期表示主动脉瓣关闭时射血的结束。随着人们开始衰老,切迹和舒张压往往会在信号中消失。(一段机翻)

PPG, VPG, and APG的基准点:
PPG: onset, systolic, notch, and diastolic peaks在这里插入图片描述

VPG: u, v, and w peaks

速度体积描记图反映时间序列振幅变化的速度,包含收缩期最大斜率点(u-peak)、舒张期最小斜率点(v-peak)和舒张期最大斜率点(w-peak)三个突出的峰,Li 等人使用了 u 峰前后的零交叉点。寻找起搏和收缩峰。w-peak 之后的零交叉点相当于舒张期峰值。它是 w-peak 和 u-peak 之间的变化(从收缩到舒张峰值所用的时间),用于测量动脉的硬度指数. 但也有振幅w不超过零的情况,舒张期出现多个低振幅正波。这可能与原始 PPG 信号上的电噪声、直流偏移或滤波偏移有关。因此,很少使用这种衍生标记。(一段机翻)
*Li:Li BN, Dong MC, Vai MI. On an automatic delineator for arterial blood pressure waveforms. Biomed Signal Process Control. (2010) 5:76–81. 10.1016/j.bspc.2009.06.002

APG: a, b, c, d, and e peaks
与 VPG 相比,APG 的分析更为频繁。APG波形中有a、b、c、d四个收缩期波和一个舒张早期e波。这里的一个关键标记是 e-peak 相当于dicrotic notch。然后,可以通过 notch 之后的第一个局部最大值来确定舒张期峰值。然而,影响波形的老化和其他病理因素会使通过这种方法检测舒张峰变得复杂。Millasseau 等人提出了另一种通过检查 VPG 来估计舒张期切迹的方法。(一段机翻)
*Millasseau : Millasseau SC, Kelly RP, Ritter JM, Chowienczyk PJ. Determination of age-related increases in large artery stiffness by digital pulse contour analysis. Clin Sci. (2002) 103:371–7. 10.1042/cs1030371
在这里插入图片描述
在这个数据上表示为:
在这里插入图片描述

PPG信号的心跳检测

预处理:去除信号趋势,bandpass,sosfilt过滤器
应用bandpass主要是去除高频噪声(如运动伪影)和低频噪声(如基线漂移),这里用了butterworth,是一种特殊的bandpass

    x_d = signal.detrend(x)
    sos = signal.butter(10, [0.5, 10], btype = 'bp', analog = False, output = 'sos', fs = fs)
    x_f = signal.sosfiltfilt(sos, x_d)

心跳检测的几种适用算法:
1: HeartPy
2: 2nd derivative maxima
3: Systolic upslopes
4: Delineator
5: qppg
6: Bishop

HeartPy

HeartPy 有自己的库可以用,github链接
可以直接pip install,

2nd derivative maxima

Systolic Peak Detection in Acceleration Photoplethysmograms Measured from Emergency Responders in Tropical Conditions里描述:
PPG信号的三种收缩峰检测方法:

  • Local Minima and Maxima 计算局部最大最小值

具体操作就是在ppg信号之后应用带通滤波器bandpass filter 以增强最大值(峰值)搜索期间的信号。再接一个阈值过滤(比如0.1),如果一个点具有最大值并且如果先前时间步长的值低于阈值,
在这里插入图片描述

  • First Derivative with Adaptive Thresholds 具有自适应阈值的一阶导数

ppg信号后用一个低通滤波器,再将过滤后的 PPG 波形分割成多个相等的部分(即,每个部分具有相同的波形样本),然后将选择窗口(持续时间为 2 秒)应用于每个部分的开始。在这些窗口内,振幅和脉搏率被估计并平均为初始阈值。然后,描绘器 delineator 以逐拍的方式搜索 PPG 波形及其导数中的拐点对 pairs of inflection 和零交叉点 zero-crossing points 。最后,在 beat evaluation 阶段,描绘器会重新检查 PPG 波形,并根据阈值估计阶段确定的振幅和间隔阈值来识别候选起始点和收缩峰。
在这里插入图片描述

  • Slope Sum function with An Adaptive Threshold 具有自适应阈值的斜率和函数

斜率的定义:在这里插入图片描述
W是分析窗口的长度,N是ppg样本总数,Δy[k]是y[n]-y[n-1],y是经过滤波的PPG信号
在这里插入图片描述
阈值计算阶段是自适应的。先将自适应阈值初始化为信号均值的三倍 Z[1 : 8fs], 记录前八秒的平均值,如下所示:在这里插入图片描述

  • Event-Related Moving Averages with Dynamic Threshold 具有动态阈值的事件相关移动平均线

该方法包括三个主要阶段:预处理(bandpass filtering and squaring)、特征提取(generating potential blocks using two moving averages)和分类(thresholding)。

在这里插入图片描述

算法伪代码:

在这里插入图片描述

实施zero-phase second-order的 Butterworth filter,bandpass 0.5–8 Hz,用于以消除对收缩峰无贡献的基线漂移 baseline wander 和高频,应用于 PPG 信号的滤波器的输出将产生一个滤波信号S[n] 然后,通过将信号裁剪在零以上来限幅输出将产生信号Z[n]。
Squaring的操作用于收缩波产生的大差异,抑制舒张波和噪声产生的小差异 y[n]等于Z[n]的平方。
————————————
第一个 moving average (MA peak) 用于强调收缩峰面积在这里插入图片描述,W1表示收缩峰持续时间的窗口大小。结果值四舍五入为最接近的奇数。
第二个 moving average (MA beat) 用于强调用作第一个 moving average 阈值的beat area 在这里插入图片描述,W2表示大约一个节拍持续时间的窗口大小。其值四舍五入为最接近的奇数。
————————————
确定偏移水平的方程式α是β* \bar{z}(Z的共轭复数),β为0.02时是强力搜索, \bar{z}是平方滤波 PPG 信号的统计平均值.。第一个动态阈值是通过将具有偏移电平的信号, THR = MAbeat(n)+α。
在这个阶段,感兴趣的块是通过比较信号MAbeat与THR,根据算法 IV 的伪代码中显示的第 9-16 行。将生成许多感兴趣的block,其中一些将包含 PPG 特征(收缩峰),而其他将主要包含噪声。因此,下一步是去除由噪声产生的block。拒绝基于预期的收缩峰宽度。在这里用阈值去除包含舒张波和噪声的block,只将包含收缩峰的block留下。

  • 评估方式和参数调整

SE = TP/(TP+FN) 和 TP/(TP+FP) 也就是precision 和recall。
改算法中主要有五个输入PPG 信号, 频带(F1–F2), 事件相关持续时间W1,W2, 和偏移量 β.
在这里插入图片描述

代码

spicy.signal.filtfilt 是用向前和向后对信号应用数字滤波器
代码来自 City University of London,自己稍作修改

def d2max(x, fs):
    """
    Detects inter-beat intervals using D2Max
    Inputs:  x, pulsatile signal [user defined units]
          fs, sampling rate [Hz]
    Outputs:  ibis, position of the starting points of inter-beat intervals [number of samples]
    
    """
    
    # Bandpass filter
    if len(x) < 4098:
        z_fill = np.zeros(4098 - len(x) + 1)
        x_z = np.append(x, z_fill)
    else:
        x_z = x
    
    # output second-order
    sos = sp.butter(10, [0.5, 8], btype = 'bandpass', analog = False, output = 'sos', fs = fs)
    x_filter = sp.sosfiltfilt(sos, x_z)
    
    # Signal clipping
    ind, = np.where(x_filter < 0)
    x_clipping = x_filter
    x_clipping[ind] = 0
    
    # Signal squaring
    x_squaring = x_clipping**2
    
    # Blocks of interest
    w1 = (111e-3)*fs
    w1 = int(2*np.floor(w1/2) + 1)
    b = (1/w1)*np.ones(w1)
    ma_peak = sp.filtfilt(b,1,x_squaring)
    
    w2 = (667e-3)*fs
    w2 = int(2*np.floor(w2/2) + 1)
    b = (1/w2)*np.ones(w1)
    ma_beat = sp.filtfilt(b,1,x_squaring)
    
    # Thresholding
    alpha = 0.02*np.mean(ma_peak)
    th_1 = ma_beat + alpha
    
    boi = (ma_peak > th_1).astype(int)
    #len(boi)=4099
    
    # Gets the difference between consecutive elements
    blocks_init, = np.where(np.diff(boi) > 0)
    blocks_init = blocks_init + 1
 
    blocks_end, = np.where(np.diff(boi) < 0)
    blocks_end = blocks_end + 1

    if blocks_init[0] > blocks_end[0]:
        blocks_init = np.append(1, blocks_init)
    if blocks_init[-1] > blocks_end[-1]:
        blocks_end = np.append(blocks_end, len(x_squaring))

    # Search for peaks inside BOIs
    len_blks = np.zeros(len(blocks_init))
    ibis = np.zeros(len(blocks_init))
    th_2 = w1

    for i in range(len(blocks_init)):
        #kind like foe loop from(0,8)len = len(blockend/block init)
        ind, = np.where(blocks_end > blocks_init[i])
        ind = ind[0]
        len_blks[i] = blocks_end[ind] - blocks_init[i]
        
        if len_blks[i] >= th_2:
            aux = x[blocks_init[i]:blocks_end[ind]]
            if len(aux) != 0:
                max_val = np.max(aux)
                max_ind, = np.where(max_val == aux)
                ibis[i] = max_ind + blocks_init[i] - 1
    
    ind, = np.where(len_blks < th_2)
    if len(ind) != 0:
        for i in range(len(ind)):
            boi[blocks_init[i]:blocks_end[i]] = 0    
    ind, = np.where(ibis == 0)
    ibis = (np.delete(ibis, ind)).astype(int)

    return ibis

upslope

引用里的指向是这篇a novel and low-complexity peak detection algorithm for heart rate estimation from low-amplitude photoplethysmographic (ppg) signals(DOI: 10.1080/03091902.2019.1572237),但是不是公开免费看的,但是好在学校账户买了许可。
该算法主要是应用于低振幅的PPG信号。在动脉脉搏跳动时,局部血容量急剧增加。这在 PPG 信号上显示为收缩峰之前的rising edge。考虑到systolic rising edge 的陡度,可以合理地假设只有当血容量达到最大值时(即收缩峰出现时),该段的斜率才会从正变为负。基于该假设,组成 systolic rising edge 的每个点 f 都满足 f(),并且提供了

算法伪代码:

在这里插入图片描述
只要PPG波的斜率是正的,变量num_steps的值就会增加,如果斜率从正变为负,num_steps将重置为零。变量possible_peak是一个标志,通过它可以忽略波纹甚至舒张期峰值,可能会被错误地标记为收缩期峰值。阈值根据经验初始化为 0.6,并随着每次心跳更新其值

代码

def upslopes(x):
    
    # Peak detection
    th = 6
    pks = np.empty(0)
    pos_pk = np.empty(0)
    pos_pk_b = 0
    n_pos_pk = 0
    n_up = 0
    
    for i in range(1, len(x)):
        if x[i] > x[i - 1]:
            n_up = n_up + 1
        else:
            if n_up > th:
                pos_pk = np.append(pos_pk, i)
                pos_pk_b = 1
                n_pos_pk = n_pos_pk + 1
                n_up_pre = n_up
            else:
                pos_pk = pos_pk.astype(int)
                #print('Possible peaks: ' + str(pos_pk) + ', number of peaks: ' + str(n_pos_pk))
                if pos_pk_b == 1:
                    if x[i - 1] > x[pos_pk[n_pos_pk - 1]]:
                        pos_pk[n_pos_pk - 1] = i - 1
                    else:
                        pks = np.append(pks, pos_pk[n_pos_pk - 1])
                    th = 0.6*n_up_pre
                    pos_pk_b = 0
            n_up = 0
    ibis = pks.astype(int)
    
    return ibis

Modified-Scholkmann algorithm

这个算法基于Scholkmann 算法,首先计算长度为 N 的线性去趋势信号X上的局部最大值尺度图 (LMS local maxima scalogram ),其中X={ xt | 1≤t≤N }。 LMS 是Smax = [N/2]−1 缩放N列的矩阵。如果时间值 t∈{1…N} 和缩放s∈{1…Smax}是局部最大矩阵包含 0,否则包含 r+α(其中 r 是均匀分布的随机变量,α 是常量)
LMS可以被视为SxN矩阵的每个scale等级的最大值,在scale为1 时,如果信号值 xt 大于相邻位置的信号值即 xt >xt-1 和 xt >xt+1,矩阵会在时间t编码局部最大值。scale 2就是xt >xt-2 和 xt >xt+2。
LMS计算从第一个scale(通常是1)到[N/2]−1,但是只裁剪1到包含最多最大值的scale。最后就是跨尺度计算列标准差column-wise standard deviation,标准偏差为零的时间点标识最大值(峰)的位置。
Multi-scale Peak and Trough Detection Optimised for Periodic and Quasi-PeriodicNeuroscience Data这篇文章针对颅内压(ICP)波形数据,测试出最大scale是等效的信号波长的四分之一左右。

后文附带了matlab代码

% ----------
% Physiology Feature Extraction Toolkit% Dr Steven Bishop, 2015-16% Division of Anaesthesia, University of Cambridge, UK% Email: sbishop {AT} doctors.org.uk
% ----------
% PEAK_TROUGH_FINDER%% Based upon the algorithm by (with updates and optimisations):
% Scholkmann F, Boss J, Wolk M. An Efficient Algorithm for Automatic Peak% Detection in Noisy Periodic and Quasi-Periodic Signals. Algorithms 2012% (5), p588-603; doi:10.3390/a5040588
% ----------
% [peaks,troughs,maximagram,minimagram] = PEAK_TROUGH_FINDER(data, {max-interval})% data: input data as vector% sampling_frequency (optional): sampling frequency of input% Returns: vectors [peaks, troughs, maximagram, minimagram] containing  
%  indices of the peaks and troughs and the maxima/minima scalograms
function [peaks,troughs,maximagram,minimagram] = new_peak_trough(data, varargin)
	N = length(data);
	if nargin == 2
		L = ceil(varargin{1}/2) -1;
	else
		L = ceil(N/2) -1;
	end
	%Detrend the data
	meanval = nanmean(data);
	data(isnan(data)) = meanval;
	data = detrend(data, 'linear');
	Mx = zeros(N, L);
	Mn = zeros(N, L);
	%Produce the local maxima scalogram
	for j=1:L
		k = j;
		for i=k+2:N-k+1
			if data(i-1) > data(i-k-1) && data(i-1) > data(i+k-1)
				Mx(i-1,j) = true;
				end
				if data(i-1) < data(i-k-1) &&data(i-1) < data(i+k-1)
				Mn(i-1,j) = true;
			end
		end
	end
	maximagram = Mx;
	minimagram = Mn;
	%Form Y the column-wise count of where Mx is 0, a scale-dependent distribution of
	%local maxima. Find d, the scale with the most maxima (== most number
	%of zeros in row). Redimension Mx to contain only the first d scales
	Y = sum(Mx==true, 1);
	[~, d] = max(Y);
	Mx = Mx(:,1:d);
	%Form Zx and Zn the row-rise counts of Mx and Mn's non-zero elements.
	%Any row with a zero count contains entirley zeros, thus indicating
	%the presence of a peak or trough
	Zx = sum(Mx==false, 2);
	Zn = sum(Mn==false, 2);
	%Find all the zeros in Zx and Zn. The indices of the zero counts
	%correspond to the position of peaks and troughs respectively
	peaks = find(~Zx);
	troughs = find(~Zn); 
end

用python改写:

def MScholkmann(x):

    # Setup
    signal = x
    N = len(signal)
    L = int(np.ceil(N / 2) - 1)

    # Step 1: calculate local maxima and local minima scalograms

    # - detrend: this removes the best-fit straight line
    x = sp.detrend(signal, type="linear")

    # - initialise LMS matrices
    m_max = np.full((L, N), False)
    # m_min = np.full((L, N), False)

    # - populate LMS matrices
    for k in range(1, L):  # scalogram scales
        for i in range(k + 2, N - k + 1):
            if x[i - 1] > x[i - k - 1] and x[i - 1] > x[i + k - 1]:
                m_max[k - 1, i - 1] = True
    #       if x[i - 1] < x[i - k - 1] and x[i - 1] < x[i + k - 1]:
    #           m_min[k - 1, i - 1] = True

    # Step 2: find the scale with the most local maxima (or local minima)
    # - row-wise summation (i.e. sum each row)
    gamma_max = np.sum(m_max, axis=1)
    # the "axis=1" option makes it row-wise
    #gamma_min = np.sum(m_min, axis=1)
    # - find scale with the most local maxima (or local minima)
    lambda_max = np.argmax(gamma_max)
    #lambda_min = np.argmax(gamma_min)

    # Step 3: Use lambda to remove all elements of m for which k>lambda
    m_max = m_max[: (lambda_max + 1), :]
    #m_min = m_min[: (lambda_min + 1), :]

    # Step 4: Find peaks (and onsets)
    # - column-wise summation
    m_max_sum = np.sum(m_max == False, axis=0)
    #m_min_sum = np.sum(m_min == False, axis=0)
    peaks = np.asarray(np.where(m_max_sum == 0)).astype(int)
    #onsets = np.asarray(np.where(m_min_sum == 0)).astype(int)
    
    return peaks

其他

自动描绘器(论文是应用于ABP)

On an automatic delineator for arterial blood pressure waveforms
动脉血压 (ABP) 波形实际上由两个不同的分量调制,即心脏压力信号 cardiac pressure signaling 和迭代脉搏波反射 iterative pulse wave reflection
请添加图片描述
还有什么就再补充吧

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/651384.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

从零开始理解Linux中断架构(3)--Armv8体系架构

首先让我们带着问题进入到armv8架构的学习中。linux中断代码分为两部分entry.S @arch\arm64\kernel\entry.S汇编部分和C代码后续处理。汇编代码中处理最为低级的部分,设置硬件中断向量表,保持当前上下文,切换中断堆栈等任务,这是就如我们嵌入式系统看到那样。 @arch\arm64…

Vue3中div自由拖拽宽度和高度。

Vue3中我们会遇到自由拖拽宽度和高度的页面需求&#xff0c;查看很多方法都无法满足当前需求。下面是我们Vue3版本的代码&#xff0c;非常简单主要构想说粗发拖拽方法&#xff0c;把所需要的div的高宽进行拖拽位置进行监听来加减自身div的px值。直接复制粘贴就可以实现效果。根…

20230615整理(字符设备驱动的内部实现)

1.1 字符设备&#xff1a; 以字节流的形式进行访问&#xff0c;而且只能顺序访问的设备叫做字符设备(比如键盘、鼠标) (块设备&#xff1a;有固定访问大小&#xff0c;可以不按顺序访问的设备&#xff0c;比如U盘、硬盘) 针对字符设备编写的驱动叫做字符设备驱动 1.2 当设备驱…

AI实战营:通用视觉框架OpenMMLab底层视觉与MMEditing

目录 图像超分辨率 Super Resolution ​​​ 深度学习时代的超分辨率算法 卷积网络模型SRCNN FSRCNN SRResNet Super-Resolution CNN, SRCNN, 2014 Fast SRCNN 2016 SRResNet 2016 对抗生成网络介绍Ganerative Adversarial Network 基于GAN的模型SRGAN与ESRGAN S…

vite+vue3+ts 报错和解决办法汇总

1. import path from path 时 ts 报错&#xff1a;模块 ""path"" 只能在使用 "allowSyntheticDefaultImports" 标志时进行默认导入。 在 tsconfig.node.json 文件的 compilerOptions 添加配置 "allowSyntheticDefaultImports": true …

【Python】Django 基础知识 一

系列文章目录 提示&#xff1a;阅读本章之前&#xff0c;请先阅读目录 文章目录 系列文章目录前言安装启动项目查看所有子命令主要文件setting 配置项URL 请求路径path 转换器HttpResponse 输出中文乱码 前言 安装 django-admin startproject xxx项目名启动项目 python manag…

ffmpeg 3.4 windows编译安装

准备工作: msys2安装 官网 MSYS2 下载完成后一直下一步即可&#xff0c;安装完成后windows搜索 MSYS2 启动MSYS2 MINGW64 打开窗口后运行以下命令 下载一些编译需要的东西 #修改源 sed -i "s#mirror.msys2.org/#mirrors.ustc.edu.cn/msys2/#g" /etc/pacman.d/mirr…

拔剑四顾心茫然,绿源直呼“行路难”

老牌两轮电动车品牌绿源上市之旅“多歧路”。 6月7日&#xff0c;北京市市场监督管理局公布北京市电动自行车产品质量监督抽查结果&#xff0c;绿源两款电动自行车因存在问题被点名&#xff0c;充电器和蓄电池、整车质量、控制系统等不符合标准。 而就在一周多以前&#xff0c…

指针(四)

文章内容&#xff1a; 1. 数组参数、指针参数 2. 函数指针 3. 函数指针数组 4. 指向函数指针数组的指针 5. 回调函数 文章内容 1. 数组参数、指针参数 地址需要指针接收&#xff0c;指针的地址需要二级指针接受,以此类推...... 1.1 一维数组传参 #include <stdio.…

【思考】技术人该如何准备晋升答辩?

文章目录 前言一、争取获得答辩机会二、准备答辩素材三、根据素材&#xff0c;编写答辩 PPT四、晋升答辩素材 PPT 的一些建议五、要写答辩稿并加以练习六、调整答辩心态总结 前言 今天跟大家聊下关于技术人该如何准备晋升答辩的话题。 每到年中或者年底&#xff0c;都会有一波…

微前端探秘:初始微前端、现有方案和未来趋势

初识微前端 微前端是什么 概念&#xff1a; 微前端是指存在于浏览器中的微服务。 微前端是一种类似于微服务的架构&#xff0c;它将微服务的理念应用于浏览器端&#xff0c;即将单页面前端应用由单一的单体应用转变为把多个小型前端应用聚合为一体的应用。这就意味着前端应用…

OpenMMLab-AI实战营第二期——6-1. 底层视觉与MMEditing

文章目录 1. 图像超分辨率&#xff08;Super Resolution&#xff09;1.1 概念1.2 目标1.3 应用1.4 分类1.4-2 单图超分的解决思路1.5 ill-posed problem和算子 2. 经典超分辨率算法&#xff08;稀疏编码Sparse Coding&#xff09;2.1 基本概念2.2 基本流程2.3 缺点 3. 深度学习…

【Java项目】1000w数据量的表如何做到快速的关键字检索?

文章目录 需求解决思路基本设计查询流程插入流程修改流程删除流程 优化思路代码实现 需求 ok&#xff0c;这个需求是我提的&#xff0c;然后我问了我的一位杭州的朋友&#xff0c;然后我们最后一起敲定这个方法。 我的项目有一个根据关键字进行商品名称的搜索功能&#xff0c…

设计模式(十九):行为型之中介者模式

设计模式系列文章 设计模式(一)&#xff1a;创建型之单例模式 设计模式(二、三)&#xff1a;创建型之工厂方法和抽象工厂模式 设计模式(四)&#xff1a;创建型之原型模式 设计模式(五)&#xff1a;创建型之建造者模式 设计模式(六)&#xff1a;结构型之代理模式 设计模式…

C语言学习笔记:结构化程序设计思想

✨博文作者&#xff1a;烟雨孤舟 &#x1f496; 喜欢的可以 点赞 收藏 关注哦~~ ✍️ 作者简介: 一个热爱大数据的学习者 ✍️ 笔记简介&#xff1a;作为大数据爱好者&#xff0c;以下是个人总结的学习笔记&#xff0c;如有错误&#xff0c;请多多指教&#xff01; 目录 自顶向…

基于51单片机设计的呼吸灯

一、项目介绍 呼吸灯是一种常见的LED灯光效果,它可以模拟人类呼吸的变化,使灯光看起来更加柔和和自然。51单片机是一种广泛使用的微控制器,具有体积小、功耗低、成本低等优点,非常适合用于控制LED呼吸灯。本项目的呼吸灯将使用PWM(脉冲宽度调制)技术控制LED亮度,从而实…

HX8358A功放IC规格书

HX8358A AB /D 类切换,最高7V供电10W 输出功率,单通道音频功率放大器 概要 HX8358A是一款FM无干扰、带防破音AB/D类可切换、高效率、无滤波器的10W单声道音频功率放大器。超低的EMI非常适合应用于带FM功能的便携式设备中。 HX8358A的单端输入架构和极高的PSRR有效地提高了HX835…

程序员一眼就会爱上的 7 个网站

作为程序员&#xff0c;您可以经常发现并学习最新的工具&#xff0c;这些工具可以帮助您提高知识、跟上新兴技术并与其他程序员建立联系。今天给大家分享7个非常有意思的网站。 HackerRank 地址&#xff1a;https://www.hackerrank.com/ HackerRank提供各种编码挑战和竞赛&am…

C国演义 [第三章]

第三章 组合分析步骤递归函数的返回值和参数递归结束的条件单层逻辑 组合总和 III 组合 力扣链接 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1…

【STM32训练—WiFi模块】第二篇、STM32驱动ESP8266WiFi模块获取天气

目录 第一部分、前言 1、获取心知天气API接口 2、硬件准备 第二部分、电脑串口助手调试WIFI模块获取天气 1、ESP8266获取天气的流程 2、具体步骤 第三部分、STM32驱动ESP8266模块获取天气数据 1、天气数据的解析 1.1、什么函数来解析天气数据&#xff1f; 2.1、解析后…