Unet心电信号分割方法(Pytorch)

心血管疾病是一种常见病,严重影响人们的健康及日常生活。 近年来随着人们生活习惯的不断变化,心血管疾病对人们影响愈加明显,发病率呈现出逐年攀升的趋势,心血管疾病是中国城乡居民死亡的首要原因。心电图ECG已被广泛用于研究心跳活动。作为一种无创的方法,ECG的相关研究为了解心脏的功能提供了便利。对心电图进行有效分析可以为心血管疾病的诊断和防治提供丰富的信息,进而大大减缓心血管疾病对人们生活的影响。

心电信号分割是心电图解读的第一步,通过心电信号分割,有助于进一步对运动员心脏健康状况进行分析,进而减少运动员受伤、致病及运动中猝死的风险。

from typing import Union,List, Tuple
# get signal with wfdb library# using an indexdef get_signal(index:int, as_p_signal:bool=True) -> Union[wfdb.Record, np.ndarray]:    record = wfdb.rdrecord(DATA_FOLDER + "/" +  str(index))    assert type(record) is wfdb.Record
    if as_p_signal:        assert type(record.p_signal) is np.ndarray        return record.p_signal            return record
# get annotations given the ecg leaddef get_annotations(index:int, lead, as_sample=True) -> Union[wfdb.Annotation, np.ndarray]:    annotations = wfdb.rdann(DATA_FOLDER +"/" + str(index), extension = lead)    if as_sample:        return np.array(annotations.sample)    return annotations
# get a full EGC with 12 leadsdef get_full_ecg(index:int):    signal = get_signal(index)    annotations = [        get_annotations(index, lead) for lead in LEADS    ]    return signal, annotations

def get_single_lead_ecg(index, lead) -> Tuple[np.ndarray, np.ndarray]:    """    return and ecg signal and its annotations    both as ndarray    """    signal = get_signal(index)    assert type(signal) is np.ndarray    signal = signal[:, LEADS.index(lead)]
    samples = get_annotations(index, lead)    assert type(samples) is np.ndarray        return signal, samples

def get_annotations_symbols(index, lead):    ann = get_annotations(index, lead, as_sample=False)    return ann.symbol
def paired_annotation_sample_and_symbol(index, lead):    annotations_symbols = get_annotations_symbols(index, lead)    annotations_sample = get_annotations(index, lead)    return zip(annotations_sample, annotations_symbols)

def get_single_lead_ecg_with_symbols(index, lead):    """    return and ecg signal and its annotations    both as ndarray    """    signal = get_signal(index)    assert type(signal) is np.ndarray    signal = signal[:, LEADS.index(lead)]
    data = paired_annotation_sample_and_symbol(index, lead)        return signal, np.array(list(data))
# plot single lead ecg with annotationsdef plot_single_lead_ecg(index, lead):    signal, samples = get_single_lead_ecg(index, lead)
    fig, ax = plt.subplots(figsize = (28, 3))
    ax.plot(signal)    ax.scatter(samples, signal[samples], c = 'r', marker = 'o')

# now plot every lead with annotationsdef plot_signal_with_annotation(index):    signal, samples = get_full_ecg(index)    # extract sample from annotations    wfdb.plot_items(signal, samples )
plot_signal_with_annotation(index = 199)

图片

class EGCSignal:    """    This class has 4 main purposes:    1. To store the signal and its annotations    2. To cut the signal once at the beginning and once at the end    3. To plot the ECG in different ways    4. To convert the annotation in a one hot encoding
    Note that doesn't store the entire ECG, but only one lead
    Also has a method to initialize the class without explicitly passing the signal and annotations    but with the index and lead of the record    """    def __init__(self, signal, time_points, symbol, categories = None):        self.signal:np.ndarray = signal        self.time_points:np.ndarray = time_points        self.symbols:list[str] = symbol        self.symbol_to_category = {            'N': 0,            't': 1,            'p': 2        }        self.category_to_symbol = {            0: 'N',            1: 't',            2: 'p'        }        self.categories = categories if categories is not None else self.symbols_to_category()        self._cut_beginning( 550)        self._cut_end( 3500)
    def __getitem__(self, key):        return self.signal[key]
    def __len__(self):        return len(self.signal)
    def _cut_beginning(self, start_point):        self.signal = self.signal[start_point:]        self.categories = self.categories[start_point:]
        # now have to check if time_points and symbols are also to cut        if start_point > self.time_points[0]:            # get the index of the first time point greater than start_point            index = np.argmax(self.time_points > start_point)                            self.time_points = self.time_points[index:]            self.symbols = self.symbols[index:]
        self.time_points = self.time_points - start_point
        # check the cut point        if self.categories[0] != -1:            # if the first symbol is a ')' then i have to prepend a '(' and a letter from self.category_to_symbol            if self.symbols[0] == ')':                self.symbols = ['('] + [self.category_to_symbol[self.categories[0]]] + self.symbols                self.time_points = np.concatenate(([0,1], self.time_points))            elif self.symbols[0] in self.symbol_to_category:                # just prepend '('                self.symbols = ['('] + self.symbols                self.time_points = np.concatenate(([0], self.time_points))
    def _cut_end(self, end_point):        self.signal = self.signal[:end_point]        self.categories = self.categories[:end_point]
        index = self.time_points[self.time_points < self.signal.size].size        self.time_points = self.time_points[:index]        self.symbols = self.symbols[:index]
        # check the cut point        if self.categories[-1] != -1:            # if the last symbol is a '(' then i have to append a ')' and a letter from self.category_to_symbol            if self.symbols[-1] == '(':                self.symbols = self.symbols +  [self.category_to_symbol[self.categories[-1]]] + [')']                self.time_points = np.concatenate((self.time_points, [self.signal.size - 1, self.signal.size ]))            elif self.symbols[-1] in self.symbol_to_category:                # just append ')'                self.symbols = self.symbols + [')']                self.time_points = np.concatenate((self.time_points, [self.signal.size]))     def plot(self, ax=None):        if ax is None:            fig, ax = plt.subplots(figsize = (28, 3))        ax.plot(self.signal)
    def plot_with_time_point(self):        fig, ax = plt.subplots(figsize = (28, 3))        self.plot(ax)        ax.scatter(self.time_points, self.signal[self.time_points], c = 'r', marker = 'o')
    def plot_with_segments(self):        fig, ax = plt.subplots(figsize = (28, 3))        self.plot(ax)
        for start, symbol, end in grouped(self.time_points, 3):                        i = np.nonzero(self.time_points == symbol)[0][0]            current_symbol = self.symbols[i]            color = SEGMENT_TO_COLOR[current_symbol]            ax.axvspan(start, end, color=color, alpha=0.4)
    def symbols_to_category(self):        """        converts the symbols list in a numpy array of integers        same length as the signal        """
        # first instantiate an array of -1 same length as the signal        category = np.full(len(self.signal), -1)        # now fill the array with the known category        for section in grouped(self.time_points):            # unpack the section            start, peak, end = section                                    # get the category given the peak            i = np.nonzero(self.time_points == peak)[0][0]            current_symbol = self.symbols[i]
            category[start:end] = self.symbol_to_category[current_symbol]
        return category
    @staticmethod    def from_index_and_lead(index, lead):        return EGCSignal(        get_signal(index)[:, LEADS.index(lead)],        get_annotations(index, lead),        get_annotations_symbols(index, lead) )


EGCSignal.from_index_and_lead(1, LEADS[0]).plot_with_segments()

图片

# plot categories on ecgsignal = X_test[ecg_index]categories = np.argmax(Y_test[ecg_index], axis=1)predicted_categories = np.argmax(Y_test_pred[ecg_index], axis=1)
# get time point where category changestime_points = np.where(categories[:-1] != categories[1:])[0]
# chek if category was at beginning or endif categories[0] != 0:    # if category was at beginning, add first time point    time_points = np.append(0, time_points)if categories[-1] != 0:    # if category was at end, add last time point    time_points = np.append(time_points, len(categories))
# plot the signalplt.figure(figsize=(10, 4))plt.plot(signal)for b,e in grouped(time_points, 2):    plt.axvspan(b, e, facecolor='0.5', alpha=0.5)

图片

signal = X_test[ecg_index]categories = np.argmax(Y_test[ecg_index], axis=1)predicted_categories = np.argmax(Y_test_pred[ecg_index], axis=1)
# get time point where category changestime_points = np.where(predicted_categories[:-1] != predicted_categories[1:])[0]

# chek if category was at beginning or endif predicted_categories[0] != 0:    # if category was at beginning, add first time point    time_points = np.append(0, time_points)if predicted_categories[-1] != 0:    # if category was at end, add last time point    time_points = np.append(time_points, len(predicted_categories))
# plot the signalplt.figure(figsize=(10, 4))plt.plot(signal)for b,e in grouped(time_points, 2):    plt.axvspan(b, e, facecolor='0.5', alpha=0.5)

图片

plt.figure(figsize=(10, 4))
plt.plot(signal, color = "gray")plt.plot(pred[:,0]*signal, alpha=0.5) # predicted not interesting
plt.plot(pred[:,3]*signal, alpha=0.9, label= "p", c=SEGMENT_TO_COLOR['p']) # predicted p
plt.plot(pred[:,1]*signal, alpha=0.9, label= "qrs", c=SEGMENT_TO_COLOR['N']) # predicted qrsplt.plot(pred[:,2]*signal, alpha=0.9, label= "t", c=SEGMENT_TO_COLOR['t']) # predicted t
plt.legend(    loc='upper right',    ncol=1,
)

图片

from matplotlib.collections import LineCollectionfrom matplotlib.colors import ListedColormap
x   = np.arange(len(signal)) t = np.linspace(0,1,x.shape[0]) # your "time" variable
lightblue  = [(0.3, 0.5, 0.9, 0.99 * p) for p in pred[:,1]]lightred   = [(0.99, 0.6, 0.5, 0.99 * p) for p in pred[:,2]]lightgreen = [(0.55, 0.99, 0.66, 0.99 * p) for p in pred[:,3]]

# set up a list of (x,y) pointspoints = np.array([x,signal]).transpose().reshape(-1,1,2)segs = np.concatenate([points[:-1],points[1:]],axis=1)
# make the collection of segmentslcblue = LineCollection(segs, cmap=ListedColormap( lightblue))lcblue.set_array(t)lcred = LineCollection(segs, cmap=ListedColormap( lightred))lcred.set_array(t)lcgreen = LineCollection(segs, cmap=ListedColormap( lightgreen))lcgreen.set_array(t)

# plot the collectionplt.figure(figsize=(15, 5))plt.plot(signal, alpha = 0.4, linewidth = 2, color='gray')plt.gca().add_collection(lcblue) # add the collection to the plotplt.gca().add_collection(lcred) # add the collection to the plotplt.gca().add_collection(lcgreen) # add the collection to the plotplt.xlim(x.min(), x.max()) # line collections don't auto-scale the plotplt.ylim(signal.min(), signal.max())

图片

工学博士,担任《Mechanical System and Signal Processing》《中国电机工程学报》《控制与决策》等期刊审稿专家,擅长领域:现代信号处理,机器学习,深度学习,数字孪生,时间序列分析,设备缺陷检测、设备异常检测、设备智能故障诊断与健康管理PHM等。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

PHP CGI Windows平台远程代码执行漏洞(CVE-2024-4577)复现

PHP语言在设计时忽略了Windows对字符编码转换的 Best-Fit 特性&#xff0c;导致未授权的攻击者可以通过特定字符串绕过 CVE-2012-1823 补丁&#xff0c;执行任意PHP代码&#xff0c;导致服务器失陷。 1.漏洞级别 高危 2.漏洞搜索 fofa: app"XAMPP"3.影响范围 P…

RTOS笔记--资源管理

资源管理 资源管理&#xff0c;其实就是前面介绍过的通知方式中的队列信号量互斥量等是如何访问临界资源的&#xff0c;如何做到完全互斥。 在之前举过一个例子&#xff1a;当我们使用全局变量来进行互斥操作时&#xff0c;有可能在改写全局变量时被切换使得不再互斥&#xff0…

使用thymeleaf直接渲染字符串

目录 一、依赖 二、示例代码 一、依赖 <--JAVA 8--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId><version>2.7.18</version></dependency><-…

如何确保数据跨域交换安全、合规、可追溯性?

数据跨域交换是指在不同的组织、系统或网络之间进行数据的传输和共享。随着数字经济的发展&#xff0c;数据跨域交换在促进数据流通和创新融合方面发挥着重要作用。然而&#xff0c;这一过程也面临着诸多挑战和风险&#xff0c;例如数据安全、合规性、完整性以及责任不清晰等问…

C#操作MySQL从入门到精通(17)——使用联结

前言: 我们在查询数据的过程中有时候查询的数据不是来自一个表而是来自多个表,本文使用的测试数据如下: 本文使用了两个表student_info、address_info student_info的数据如下: address_info的数据如下: 1、内联结 所谓内联结就是求交集,两个表都有的数据才是有效数…

SSH密钥认证:实现远程服务器免密登录的两种方法|Linux scp命令详解:高效实现文件与目录的远程传输

简介&#xff1a; 服务器之间经常需要有一些跨服务器的操作&#xff0c;此时就需要我们在一台服务器上登录到另外一台服务器&#xff0c;若是人为操作时我们都可以每次输入密码进行远程登录&#xff0c;但要是程序需要跨服务器时&#xff0c;每次输入密码就不现实了&#xff0c…

Java 开发实例:Spring Boot+AOP+注解+Redis防重复提交(防抖)

文章目录 1. 环境准备2. 引入依赖3. 配置Redis4. 创建防重复提交注解5. 实现AOP切面6. 创建示例Controller7. 测试8. 进一步优化8.1 自定义异常处理8.2 提升Redis的健壮性 9. 总结 &#x1f389;欢迎来到Java学习路线专栏~探索Java中的静态变量与实例变量 ☆* o(≧▽≦)o *☆嗨…

基于单片机的数控稳压开关电源研究

为了解决多种类供电的电压需求&#xff0c;克服供电电路体积大、性价比低的问题&#xff0c;复杂电路系统以单片机控制为核心&#xff0c;尝试构建单片机数控开关稳压电源的硬件平台&#xff0c;并开发软件程序&#xff0c;实现系统多种类供电电压输出的控制。实验证明&#xf…

zabbix老版本3.0.14迁移

由于之前zabbix版本过老&#xff0c;一直未能升级&#xff0c;现在一台老的服务器需要迁移&#xff0c;服务器较老&#xff0c;就不更新&#xff0c;先迁移数据&#xff0c; 下载地址&#xff1a; Zabbix Official Repository http://repo.zabbix.com/zabbix/3.0/rhel/7/x86…

「实战应用」如何用DHTMLX将上下文菜单集成到JavaScript甘特图中(一)

DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表。可满足项目管理应用程序的所有需求&#xff0c;是最完善的甘特图图表库。 DHTMLX Gantt是一个高度可定制的工具&#xff0c;可以与项目管理应用程序所需的其他功能相补充。在本文中您将学习如何使用自定义上…

如何使用Spring Boot框架整合Redis:超详细案例教程

目录 # 为什么选择Spring Boot与Redis整合&#xff1f; 1. 更新 pom.xml 2. 配置application.yml 3. 创建 Redis 配置类 4. Redis 操作类 5. 创建控制器 6. 启动应用程序 7. 测试 # 为什么选择Spring Boot与Redis整合&#xff1f; 将Spring Boot与Redis整合可以充分利…

自制一个Linux live固件镜像ISO可引导系统

使用母盘镜像制作两个虚拟&#xff0c;来制作一个包含基本需求的filesystem.squashfs文件&#xff0c;具体看下面的链接 使用的安装镜像 是Linux Mint 制作好的成品 https://cloud.189.cn/t/U32Mvi7FnyA3 &#xff08;访问码&#xff1a;2nbo&#xff09; 最简单制作LIVE CD…

java多线程概念

在Java多线程编程中有几个重要的概念&#xff0c;这些概念对于理解和编写正确的多线程应用程序至关重要&#xff1a; 1.线程&#xff08;Thread&#xff09;: 线程是操作系统能够进行运算调度的最小单位&#xff0c;Java通过线程实现并发执行。 2.进程&#xff08;Process&…

12_YouOnlyLookOnce(YOLOv3)新一代实时目标检测技术

1.1 回顾V1和V2 V1&#xff1a;05_YouOnlyLookOnce(YOLOV1)目标检测领域的革命性突破-CSDN博客 V2&#xff1a;07_YouOnlyLookOnce(YOLOv2)Better&#xff0c;Faster&#xff0c;Stronger-CSDN博客 1.2 简介 YOLOv3&#xff08;You Only Look Once version 3&#xff09;是…

【odoo】odoo中对子数据的独有操作[(0, 0, {‘name‘: ‘demo‘})]

概要 在Odoo中&#xff0c;有种写法用于操作 one2many 或 many2many 字段时&#xff0c;描述如何在数据库中创建、更新或删除相关记录。具体而言&#xff0c;这是一种命令格式&#xff0c;被称为 "commands" 或 "special command tuples"&#xff0c;用于 …

[大模型]Qwen2-7B-Instruct vLLM 部署调用

vLLM 简介 vLLM 框架是一个高效的大语言模型推理和部署服务系统&#xff0c;具备以下特性&#xff1a; 高效的内存管理&#xff1a;通过 PagedAttention 算法&#xff0c;vLLM 实现了对 KV 缓存的高效管理&#xff0c;减少了内存浪费&#xff0c;优化了模型的运行效率。高吞吐…

Nginx负载均衡之长连接负载均衡

当客户端通过浏览器访问 HTTP 服务器时&#xff0c;HTTP 请求会通过 TCP 协议与 HTTP 服务器建立一条访问通道&#xff0c;当本次访问数据传输完毕后&#xff0c;该 TCP 连接会立即被断开&#xff0c;由于这个连接存在的时间很短&#xff0c;所以 HTTP 连接也被称为短连接。 …

五、特征缩放和多项式回归

目录 一、为什么要使用特征缩放(Feature Scaling) 1.首先来看预测房价的例子 2.特征缩放前后效果对比 二、特征缩放方法 1.统一除以范围最大值 2.均值归一化(Mean Normalization) 3.Z-score标准化(Z-score Normalization) 4.一些可以接受/不接受的缩放范围 三、如何识别…

使用docker构建自己的镜像并推送到远程镜像仓库

这里镜像仓库使用阿里云仓库&#xff0c;其他仓库可能类似&#xff0c;可以参考&#xff0c;个人实例可以免费使用。 背景 遇到的问题&#xff1a;需要定制一个自己的镜像&#xff0c;在上面安装一些环境&#xff0c;然后将镜像托管到公共镜像仓库&#xff0c;在其他地方使用…

14.基于人类反馈的强化学习(RLHF)技术详解

基于人类反馈的强化学习&#xff08;RLHF&#xff09;技术详解 RLHF 技术拆解 RLHF 是一项涉及多个模型和不同训练阶段的复杂概念&#xff0c;我们按三个步骤分解&#xff1a; 预训练一个语言模型 (LM) &#xff1b;训练一个奖励模型 (Reward Model&#xff0c;RM) &#xf…