脑电波控制设备:基于典型相关分析(CCA)的脑机接口频率精准解码方法

news2025/3/14 14:01:14

文章目录

  • 前言
  • 一、CCA的用途
  • 二、频率求解思路
  • 三、输入数据结构
  • 四、判断方法
  • 五、matlab实践
    • 1.数据集获取及处理
    • 2.matlab代码
    • 3.运行及结果
  • 六、参考文献


前言

        在脑机接口(BCI)领域,有SSVEP方向,中文叫做稳态视觉诱发电位,当人观看闪烁的视觉刺激(比如闪烁的灯光或图像)时,大脑会在与刺激频率一致的频率上,产生电位波动。这段脑电波是一种稳定且容易检测的脑电信号。通过确定ssvep波的频率,可以准确地判断用户正专注于哪个视觉刺激目标,帮助BCI系统识别用户意图,从而控制相应的设备或应用。例如,用户可以通过注视不同频率的方块或图标来控制计算机光标、游戏角色、轮椅等设备。还可以通过确定频率成分,对脑部健康状况进行初步筛查或监控,进而识别一些可能的脑部异常活动。
在这里插入图片描述


一、CCA的用途

        过去广泛使用的频率检测方法是PSDA,基于功率谱密度的分析,例如傅里叶变换,小波变换等。CCA(典型相关分析,Canonical Correlation Analysis) 是一种多变量统计分析方法,用于研究两组变量之间的相关性。在SSVEP-BCI(稳态视觉诱发电位-脑机接口)系统中,通常利用CCA来提取信号的频率特征并解码用户的意图。CCA的核心目标是通过求解典型相关系数来寻找两个信号集之间的关联性。

The most widely used frequency detection method in SSVEP-based BCIs is power spectral density based analysis。(PSDA)在基于SSVEP的脑机接口中,最广泛使用的频率检测方法是基于功率谱密度的分析。


二、频率求解思路

        使用CCA,需要输入两个变量, X X X Y Y Y X X X 是采集到的数据, Y Y Y 是用已知的标准正余弦信号做为模板进行预设的数据。CCA旨在找到一对变换矩阵 A A A B B B ,使得变换后的两个信号集之间的相关性最大化。相关性就体现在相关系数 p p p 的求解上:
max ρ = cov ( A X , B Y ) cov ( A X , A X ) ⋅ cov ( B Y , B Y ) \text{max} \quad \rho = \frac{ \text{cov}(A X, B Y) }{ \sqrt{ \text{cov}(A X, A X) \cdot \text{cov}(B Y, B Y) } } maxρ=cov(AX,AX)cov(BY,BY) cov(AX,BY)
        在得到的所有系数中,找到最大的系数。最大系数对应的频率,与SSVEP波频率相关性最大,就代表了SSVEP波的频率就是这个值。


三、输入数据结构

        使用数据结构说明如下描述,看图辅助文字理解。输入 x x x 的行数为通道数8, x x x 是采集到的数据。输入 y y y 行数为使用的谐波数6, y y y 是标准正余弦信号。 x x x y y y 两者的列数为时间t。
        输入的 x x x y y y 数据结构如下图
x是采集到的数据,y是标准正余弦信号
         y y y 是标准正余弦信号,是下图这样的形式
y是标准正余弦信号

CCA works on two sets of variables. In our method, variables in one set are the signals, x(t),recorded from several channels within a local region and the second set is from stimulus signals.
CCA处理两组变量。在我们的方法中,一组变量x(t)是从局部区域内的几个通道记录的信号,第二组变量来自刺激信号。


四、判断方法

        相关系数最大时的频率,就是我们要找的频率。而相关系数 p = λ 2 p=λ² p=λ2 ,这个关系由CCA理论推导得到。篇幅所限这里只记结论,详情可以看这篇,理论学习部分典型相关分析(CCA)探索多维数据间的深层关系:基于Matlab,内有详细推导,包教包会。这里想求出 p p p ,只要找到对应特征值,开根号就好了。

找到最大的p对应的频率

Suppose there are K stimulus frequencies f1,f2,…fk and that the analyzed signal has been acquired from N channels within an Ls window. Our strategy for recognition is as follows. where p(f) is the CCA coefficient of xLN and y.
假设有K个刺激频率 f1,f2,…fk,并且所分析的信号是在一个长度为Ls的窗口内从N个通道中获取的。我们的识别策略如下。刺激频率fs满足 p(f) 是 xLN 和 y 的 CCA 系数。

In this approach, EEG signals from multiple channels are used to calculate the CCA coefficients with all stimulus frequencies in the system. The frequency with the largest coefficient is the one of SSVEP.
在该方法中,使用EEG信号来自多个通道,来计算系统中所有刺激频率的CCA系数。具有最大系数的频率是SSVEP的频率。


五、matlab实践

1.数据集获取及处理

        使用清华大学脑机接口研究组的公开数据集,链接 https://bci.med.tsinghua.edu.cn/
        此处下载使用Wearable SSVEP BCI Dataset的S1~S10。

![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/f9f7fc600ec849d2821660cb31156572.png

        该数据集刺激信息如下图,一共12个频率。
在这里插入图片描述
        根据An Open Dataset for Wearable SSVEP-BasedBrain-ComputerInterfaces,这篇文章对该数据集的描述。

        该数据集包括102个MATLAB MAT文件,对应于102个受试者的脑电图数据。所有文件都是根据参与者的索引命名的(即S001.mat、S102.mat)。每个文件都包含一个名为“data”的5-D矩阵,维度为[8,710,2,10,12],并存储为双精度浮点值。五个维度分别表示“通道标号”、“时间点”、“电极标号”、”块标号“和”目标标号“。每个矩阵对应240个历元(12个目标×10个块×2个电极),每个历元由未经任何处理的8个通道的原始脑电图数据组成,长度为2.84s(2.84s×250=710个时间点)
        根据连续EEG数据的事件通道中记录的刺激起始点,可以提取数据历元。每个数据历元的长度为2.84s,包括刺激开始前0.5s、视觉反应延迟0.14s、刺激后2s和刺激后0.2s。为了降低存储和计算成本,所有数据都被下采样到250 Hz。

        这里因为采样频率为250hz,所以一秒可以采集250个点,所以2.84s采集 2.84 s × 250 = 710 2.84s×250=710 2.84s×250=710 点。 或者这样计算,采样点数 N N N,采样时间 T T T,采样间隔 T s Ts Ts ,采样频率 f s fs fs ,
N = T / T s N = T / Ts N=T/Ts
T s = 1 / f s Ts = 1 / fs Ts=1/fs
所以
N = 2.84 / ( 1 / 250 ) = 2.84 x 250 = 710 点 N= 2.84 / (1/250) = 2.84 x 250 = 710点 N=2.84/(1/250)=2.84x250=710
        我们只使用采集的数据验证下CCA,不需要像文章里,对不同的通道/电极做对比评测。所以只需要拿第二个维度上,710个采集数据点使用即可。在这里用的 x x x 是data_1只取8个通道刺激后2秒的数据,即2~2.84秒,只取最后0.84s的数据,对应210个点。所以 y y y 在公式中的T要用到210个值。 T / S = 210 / 250 = 0.84 T/S = 210/250 = 0.84 T/S=210/250=0.84 这也刚好说明是对应时间长度的。

2.matlab代码

        测试代码test_CCA.m如下,根据文中信息,数据 x x x 要使用8个通道的数据。对 y y y 的构建,只使用6个谐波。测试代码配合CCA算法,两个文件配合使用。这里仅读取S001.mat。
         test_CCA.m :

%*******  test_CCA.m  **********%
% 加载.mat文件
load('S001.mat');

% 获取data变量部分数据
data_1 = data(:,501:710,1,1,1);  % 8x210

% t  6x84
t = 1:210;  

% 定义要用来循环的fre的值
fre_values = [9.25, 11.25, 13.25, 9.75, 11.75, 13.75, 10.25, 12.25, 14.25, 10.75, 12.75, 14.75]; % 可以根据需要添加更多值


%% cca
x = data_1'; % 210x8
A_list = zeros([6, 12]); % 初始化存储 A 的多维数组
B_list = zeros([8, 12]); % 初始化存储 B 的多维数组
C1_list = zeros(1, length(fre_values)); % 初始化存储 C1 的单元数组

% 循环通过fre_1的值并生成相应的data_2矩阵
for i = 1:length(fre_values)
    fre = fre_values(i);
    
    data_2 = [sin(2*pi*fre*t/250);
              cos(2*pi*fre*t/250);
              sin(4*pi*fre*t/250);
              cos(4*pi*fre*t/250);
              sin(6*pi*fre*t/250);
              cos(6*pi*fre*t/250)];
    y = data_2'; % 210x6
    [A, B, C1] = CCA(x, y);
    C1_list(i) = C1;
    A_list(:, i) = A;
    B_list(:, i) = B;
end
[max_value, index] = max(C1_list);
P = sqrt(max_value);  % 相关系数p等于λ,这里特征值是λ的平方,后面开根号
fprintf('最大相关系数 p = %.5f\n', P); % %.5f 表示保留5位小数
A = A_list(:, index)
B = B_list(:, index)
fprintf('当前注视的图像频率为 %.2f Hz\n', fre_values(index)); % %.2f 表示保留两位小数

        CCA算法, CCA.m :

%********  CCA.m  *********%
function [A,B,C1]=CCA(X,Y)
%CCA canonical correlation analysis
% [A,B]=cca(X,Y)
dimx=size(X,2); dimy=size(Y,2);  %列数(变量数)
Sall = cov([X Y]);  %cov求协方差矩阵。原阵X大小为M*N,则cov(X)大小为N*N的矩阵
dim=min(dimx,dimy);
Sxx=Sall(1:dim,1:dim);
Syy=Sall(dim+1:end,dim+1:end);
Sxy=Sall(1:dim,dim+1:end);
Syx=Sall(dim+1:end,1:dim);
 
iSxx=inv(Sxx);  %矩阵求逆
iSyy=inv(Syy);
 
M1 = iSxx*Sxy*iSyy*Syx;
M2 = iSyy*Syx*iSxx*Sxy;
 
% 使用 SVD 分解
[U1, S1, V1] = svd(M1);  % M1 的奇异值分解
[U2, S2, V2] = svd(M2);  % M2 的奇异值分解
 
% 手动单位化 U1 和 U2:使得每列(奇异向量)的模长为 1
for i = 1:size(U1, 2)
    U1(:, i) = U1(:, i) / sqrt(U1(:, i)' * U1(:, i));  % 每列单位化
end
 
for i = 1:size(U2, 2)
    U2(:, i) = U2(:, i) / sqrt(U2(:, i)' * U2(:, i));  % 每列单位化
end
 
% 手动归一化 S1 和 S2,使得最大奇异值为 1
S1 = S1 / max(diag(S1));  % 将 S1 的最大奇异值归一化为 1
S2 = S2 / max(diag(S2));  % 将 S2 的最大奇异值归一化为 1
 
% A ...... 选择最大奇异值对应的奇异向量
[maxVals1, colIndex1] = max(diag(S1));  % 找到最大奇异值所在的列
A = U1(:, colIndex1);  % 选择对应的奇异向量
C1 = maxVals1;  % 最大奇异值
A = A * diag(1 ./ sqrt(A' * Sxx * A));  % 归一化,注意矩阵的大小匹配
 
% B ...... 选择最大奇异值对应的奇异向量
[maxVals2, colIndex2] = max(diag(S2));  % 找到最大奇异值所在的列
B = U2(:, colIndex2);  % 选择对应的奇异向量
B = B * diag(1 ./ sqrt(B' * Syy * B));  % 归一化,注意矩阵的大小匹配

3.运行及结果

        将测试代码test_CCA.m和CCA.m文件与数据S001.mat放到同一目录下,方便读取。
在这里插入图片描述
        运行结果为9.25hz,相关系数和 A , B A,B A,B 具体值,matlab版本不同会有轻微差异。
在这里插入图片描述

六、参考文献

CCA学习:
Z. Lin, C. Zhang, W. Wu and X. Gao, “Frequency Recognition Based on Canonical Correlation Analysis for SSVEP-Based BCIs,” in IEEE Transactions on Biomedical Engineering, vol. 53, no. 12, pp. 2610-2614, Dec. 2006, doi: 10.1109/TBME.2006.886577.

数据集来源:
Zhu F, Jiang L, Dong G, Gao X, Wang Y. An Open Dataset for Wearable SSVEP-Based Brain-Computer Interfaces. Sensors (Basel). 2021 Feb 10;21(4):1256. doi: 10.3390/s21041256.

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

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

相关文章

Android Spinner总结

文章目录 Android Spinner总结概述简单使用自定义布局自定义Adapter添加分割线源码下载 Android Spinner总结 概述 在 Android 中&#xff0c;Spinner 是一个下拉选择框。 简单使用 xml布局&#xff1a; <Spinnerandroid:id"id/spinner1"android:layout_width&…

element-ui layout 组件源码分享

layout 布局组件源码分享&#xff0c;主要从以下两个方面&#xff1a; 1、row 组件属性。 2、col 组件属性。 一、row 组件属性。 1.1 gutter 栅栏间隔&#xff0c;类型为 number&#xff0c;默认 0。 1.2 type 布局模式&#xff0c;可选 flex&#xff0c;现代浏览器下有效…

OBJ文件生成PCD文件(python 实现)

代码实现 将 .obj 文件转换为 .pcd&#xff08;点云数据&#xff09; 代码文件。 import open3d as o3d# 加载 .obj 文件 mesh o3d.io.read_triangle_mesh("bunny.obj")# 检查是否成功加载 if not mesh.has_vertices():print("无法加载 .obj 文件&#xff0c…

c++介绍智能指针 十二(1)

普通指针&#xff1a;指向内存区域的地址变量。使用普通指针容易出现一些程序错误。 如果一个指针所指向的内存区域是动态分配的&#xff0c;那么这个指针变量离开了所在的作用域&#xff0c;这块内存也不会自动销毁。动态内存不进行释放就会导致内存泄露。如果一个指针指向已…

Appium等待机制--强制等待、隐式等待、显式等待

书接上回&#xff0c;Appium高级操作--其他操作-CSDN博客文章浏览阅读182次&#xff0c;点赞6次&#xff0c;收藏7次。书接上回Appium高级操作--从源码角度解析--模拟复杂手势操作-CSDN博客。https://blog.csdn.net/fantasy_4/article/details/146162851主要讲解了Appium的一些…

计算机视觉cv2入门之图像的读取,显示,与保存

在计算机视觉领域&#xff0c;Python的cv2库是一个不可或缺的工具&#xff0c;它提供了丰富的图像处理功能。作为OpenCV的Python接口&#xff0c;cv2使得图像处理的实现变得简单而高效。 示例图片 目录 opencv获取方式 图像基本知识 颜色空间 RGB HSV 图像格式 BMP格式 …

【QT】事件系统入门——QEvent 基础与示例

一、事件介绍 事件是 应用程序内部或者外部产生的事情或者动作的统称 在 Qt 中使用一个对象来表示一个事件。所有的 Qt 事件均继承于抽象类 QEvent。事件是由系统或者 Qt 平台本身在不同的时刻发出的。当用户按下鼠标、敲下键盘&#xff0c;或者是窗口需要重新绘制的时候&…

5-27 临摹大师-IP-Adapter

前言&#xff1a; 前一节我们主要介绍ControlNet中如何对黑白照片进行上色 主要介绍ControlNet中的IP-Adapter。这个也是一种类似的风格借鉴&#xff0c;类似Reference的能力。 当然IP-Adapter有两点或许可以吸引我们&#xff0c;一个是国人腾讯公司制作的。另一个在速度和效…

Spring MVC面试题(一)

1.什么是Spring MVC&#xff1f; 全称为Model View Controller&#xff0c;Spring MVC是Spring的一个模块&#xff0c;基于MVC架构模式的一个框架 2.Spring MVC优点&#xff1f; 1.可用各种视图技术&#xff0c;不仅限于JSP 2.支持各种请求资源映射策略 3. Spring MVC工作原…

Unity开发的抖音小游戏接入抖音开放平台中的流量主(抖音小游戏接入广告)

前言:作者在进行小游戏审核版本的过程中,碰到了下列问题,所以对这个抖音小游戏接入广告研究了下。 还有就是作者的TTSDK版本号是6.2.6,使用的Unity版本是Unity2022.3.29f1,最好和作者的两个版本号保持一致,因为我发现TTSDK旧版的很多函数在新版中就已经无法正常使用了,必…

统一 Elastic 向量数据库与 LLM 功能,实现智能查询

作者&#xff1a;来自 Elastic Sunile Manjee 利用 LLM 功能进行查询解析&#xff0c;并使用 Elasticsearch 搜索模板&#xff0c;将复杂的用户请求转换为结构化的、基于模式的搜索&#xff0c;从而实现高精度查询结果。 想象一下&#xff0c;你在搜索“距离 Belongil Beach 25…

[操作系统] 学校课程关于“静态优先级抢占式调度“作业

今天我们来分享两道题目哈, 学校弄得题目. T1: 静态优先级, 抢占式(1为高优先级) 图解: 以下是静态优先级抢占式调度的解题过程和结果&#xff1a; 解题思路&#xff1a; 优先级规则&#xff1a; 数值越小优先级越高。新进程到达时&#xff0c;若其优先级高于当前运行进程&…

【SpringBoot】MD5加盐算法的详解

目录 一、什么是加盐算法 二、如何实现加盐算法 2.1 加盐算法代码实现 2.2 注册页面中进行密码加盐 2.3 登录页面进行加盐的解密 2.4 注册和登录 一、什么是加盐算法 加盐算法是一种用于增强密码安全性的技术。这种技术通过在密码存储过程中添加一个随机生成的盐值&…

累计完工数量达到了xxxx超过了最大可完工数量xxxx

之前解决过一次&#xff0c;没有记录下来&#xff0c;不记得发生什么事情。又浪费几个小时去分析问题。这次的经历有点痛苦&#xff0c;碰上多表关连数据的勾稽。分析是河南用户的非法操作造成的。没有领料记录入不了库&#xff0c;跨月了。财务要求删单处理。删单之后&#xf…

飞鸟与鱼不同路

看&#xff0c;好美的太阳。 正是因为有人看才会觉得美&#xff0c;若无人问津&#xff0c;美又从何而来。 嘿嘿&#xff0c;今天提出辞去综合教研室主任一职&#xff0c;不想在这个管理上废时间啦~ 把时间用来考试.........用来做自己的事情&#xff0c;花在自己的身上&…

若依RuoYi-Cloud-Plus微服务版(完整版)前后端部署

一.目标 在浏览器上成功登录进入 二.源码下载 后端源码&#xff1a;前往Gitee下载页面(https://gitee.com/dromara/RuoYi-Cloud-Plus)下载解压到工作目录。 前端源码&#xff1a; 前往Gitee下载页面(https://gitee.com/JavaLionLi/plus-ui)下载解压到工作目录。 文档地址&a…

【redis】list类型:基本命令(下)

文章目录 LLENLREMLTRIMLSET阻塞版本命令BLPOP 和 BRPOP区别使用方式 命令小结内部编码 LLEN 获取 list 的长度 语法&#xff1a; LLEN key时间复杂度&#xff1a; O ( 1 ) O(1) O(1)返回值&#xff1a; list 长度 LREM 删除 count 个 key 中的元素 语法&#xff1a; LREM…

【数据挖掘】知识蒸馏(Knowledge Distillation, KD)

1. 概念 知识蒸馏&#xff08;Knowledge Distillation, KD&#xff09;是一种模型压缩和知识迁移技术&#xff0c;旨在将大型复杂模型&#xff08;称为教师模型&#xff09;中的知识传递给一个较小的模型&#xff08;称为学生模型&#xff09;&#xff0c;以减少计算成本&…

VSCode 搭建C++编程环境 2025新版图文安装教程(100%搭建成功,VSCode安装+C++环境搭建+运行测试+背景图设置)

名人说&#xff1a;博观而约取&#xff0c;厚积而薄发。——苏轼《稼说送张琥》 创作者&#xff1a;Code_流苏(CSDN)&#xff08;一个喜欢古诗词和编程的Coder&#x1f60a;&#xff09; 目录 一、VScode下载及安装二、安装 MinGW-w64 工具链三、Windows环境变量配置四、检查 M…

Ubuntu24.04 LTS 版本 Linux 系统在线和离线安装 Docker 和 Docker compose

一、更换软件源并更新系统 在 Ubuntu 24.04 LTS 中&#xff0c;系统引入了全新的软件源配置格式。现在的源配置文件内容更加结构化且清晰&#xff0c;主要包含了软件类型 (Types)、源地址 (URIs)、版本代号 (Suites) 以及组件 (Components) 等信息。 # cat /etc/apt/sources.li…