一、概述
DeepBCI 是一款常用的 EEG 采集设备,支持多通道脑电信号采集。结合提供的BrainFlow库封装代码,可实现从设备初始化、数据采集到信号处理的完整流程。以下基于BoardShim(设备通信)和DataFilter(信号处理)类,梳理具体实现步骤。
二、环境与设备初始化
1. 头文件与依赖
需包含 BrainFlow 核心库头文件,主要涉及设备通信和信号处理类:
#include "board_shim.h"
#include "data_filter.h"
#include "brainflow_constants.h"
#include <vector>
2. 设备参数配置
OpenBCI Cyton 通过串口通信,需指定串口号(如 Windows 的COM3或 Linux 的/dev/ttyUSB0),对应BrainFlowInputParams结构体配置:
// 初始化设备参数
struct BrainFlowInputParams params;memset(¶ms, 0, sizeof(params));
params.serial_port = "COM3"; // 替换为实际串口号
int board_id = (int)BoardIds::CYTON_BOARD; // OpenBCI Cyton对应的board_id
3. 实例化 BoardShim 对象
BoardShim board_shim(board_id, params);
三、数据采集流程
1. 会话准备与启动
try{
// 准备会话(初始化设备连接)
board_shim.prepare_session();
// 启动数据流(缓冲区大小默认450000,可按需调整)
board_shim.start_stream();
}catch (const BrainFlowException &e)
{
// 异常处理(如设备连接失败)
std::cerr << "采集初始化失败: " << e.what() << std::endl;
return -1;
}
2. 获取原始数据
通过get_board_data获取二维数据(行:通道,列:采样点):
// 获取所有可用数据(默认预设)
BrainFlowArray<double, 2> raw_data = board_shim.get_board_data();
int num_channels = raw_data.get_size(0); // 通道数
int num_samples = raw_data.get_size(1); // 采样点数
double *data_ptr = raw_data.get_raw_ptr(); // 原始数据指针
3. 关键通道提取
OpenBCI Cyton 的 EEG 通道可通过get_eeg_channels获取,便于后续处理:
// 获取EEG通道索引(如Cyton通常为8通道)
std::vector<int> eeg_channels = BoardShim::get_eeg_channels(board_id);
四、信号预处理与特征提取(基于 DataFilter)
1. 滤波处理
针对 EEG 信号常见噪声(如工频干扰、肌电噪声),使用滤波方法:
// 示例:50Hz陷波滤波(去除工频噪声)
for (int ch : eeg_channels)
{
// 提取单通道数据(每行对应一个通道)
double *ch_data = raw_data.get_row(ch);
// 去除环境噪声(50Hz或60Hz,根据地区选择)
DataFilter::remove_environmental_noise(ch_data, num_samples, 250, (int)NoiseTypes::NOTCH_50HZ);
}
// 示例:带通滤波(保留1-50Hz EEG信号)
for (int ch : eeg_channels)
{
double *ch_data = raw_data.get_row(ch);
DataFilter::perform_bandpass(
ch_data, num_samples, 250, // 采样率250Hz(Cyton默认)
1.0, 50.0, // 通带1-50Hz
4, // 滤波器阶数
(int)FilterTypes::BUTTERWORTH, // 巴特沃斯滤波器
0.0 // 波纹系数(巴特沃斯无需设置)
);
}
2. 功率谱密度(PSD)计算
通过 FFT 计算 EEG 各频段(δ、θ、α、β、γ)功率:
// 示例:计算单通道PSDint ch = eeg_channels[0]; // 第一个EEG通道
double *ch_data = raw_data.get_row(ch);int psd_len = 0;// 计算PSD(采样率250Hz,使用汉宁窗)
std::pair<double *, double *> psd = DataFilter::get_psd(
ch_data, num_samples, 250,
(int)WindowTypes::HANN, &psd_len);
double *amplitude = psd.first; // 振幅谱
double *frequency = psd.second; // 频率轴
// 提取α波(8-13Hz)功率
double alpha_power = DataFilter::get_band_power(
psd, psd_len, 8.0, 13.0);
3. 其他常用处理
小波去噪:
DataFilter::perform_wavelet_denoising(
ch_data, num_samples,
(int)WaveletTypes::DB4, // 小波类型
3, // 分解层数
(int)WaveletDenoisingTypes::SURESHRINK);
降采样:
int downsampled_size = 0;double *downsampled_data = DataFilter::perform_downsampling(
ch_data, num_samples, 2, // 降采样倍数为2
(int)AggOperations::MEAN, // 均值聚合
&downsampled_size);
五、数据终止与资源释放
// 停止数据流
board_shim.stop_stream();// 释放会话(断开设备连接)
board_shim.release_session();// 释放动态分配的内存(如PSD结果)
delete[] amplitude;delete[] frequency;delete[] downsampled_data;
六、核心算法大概包括以下几类:
1. 工频陷波滤波(去除 50Hz/60Hz 电源干扰)
EEG 信号极易受电源干扰(50Hz 或 60Hz),这是滤波的首要任务。
算法原理:采用IIR 带阻滤波器(如双二阶陷波滤波器),在特定频率点(50/60Hz)形成衰减峰,抑制干扰而不影响其他频率成分。
实现逻辑:
设计公式:对于中心频率f0,采样率fs,品质因数Q,通过双二阶滤波器公式计算系数:
ω0=2πf0/fs
alpha=sin(ω0)/(2Q)
b0=1+alpha,b1=−2cos(ω0),b2=1−alpha
a0=1+alpha,a1=−2cos(ω0),a2=1−alpha
BrainFlow 会根据设备采样率(如 BrainBit 的 250Hz,见brainflow_boards.cpp)自动适配滤波器参数。
2. 高通滤波(去除基线漂移)
EEG 信号中的低频漂移(如 < 0.5Hz)会掩盖慢电位变化,需通过高通滤波去除。
算法选择:通常采用一阶或二阶 IIR 高通滤波器(如巴特沃斯滤波器),截止频率设为 0.5Hz 或 1Hz。
优势:IIR 滤波器计算量小,适合实时处理(符合 BrainFlow 的实时性要求)。
3. 低通滤波(去除高频噪声)
肌肉电(EMG)、环境电磁噪声等高频信号(如 > 50Hz)会干扰 EEG,需通过低通滤波限制带宽。
算法选择:巴特沃斯低通滤波器(二阶或四阶),截止频率通常设为 30Hz(针对 α、β 波)或 50Hz(保留 γ 波)。
与设备的适配:根据brainflow_boards.cpp中定义的设备采样率(如 Cyton 的 250Hz、Ganglion 的 200Hz),动态调整滤波器系数以避免混叠。
4. 数据预处理:基线校正与标准化
基线校正:计算一段时间窗口内的信号均值(如前 100ms 数据),从当前信号中减去均值,消除直流偏移。
标准化:将信号缩放到 [-1,1] 或特定范围(如微伏级),公式:
xnorm=(x−xmin)/(xmax−xmin)
- 使用C++重写类似OpenBCI GUI:
- 开发环境搭建:wxWidgets +gcc ,使用国人自行开发的小熊猫集成开发环境。
- 已经实现基本的采集数据显示,集成了上面写的的关键的算法。
- 验证硬件DeepBCI 完全兼容OpenBCI cyton 可以直接代替。