算法思路:
这是2020年江苏省电赛A题的一部分设计要求,计算ADS1292模块传出的心电信号值,找到QRS坐标,ADS1292是一个24位高精度的ADC,通过两路的差分放大接收激励引脚产生的电压变化(心电信号的变化)。
ECG信号为准周期信号,R为一个波段的最大值,Q为R前的最小值,S为整个波段最小值(R后最小值),信号建议使用SG滤波,可以保留信号变化的一种类似于最小二乘法的滤波,然后对数组取差值,前后差值最大的点为R,R前差值为正,直到Q点,R后插值为负,直到S点。
代码:
提示:这是对一组250个采样点,分区间找最大值,判断组内有效心电信号波段个数,计算相应QRS坐标的简易算法,用的一组处理后的心电数据txt里的。
#include <stdio.h>
#include <math.h>
int main(void)
{
int i,j,max_piont[6]={0},min1_piont[6]={0},min2_piont[6]={0},sz[461],max[6]={0},min1[6]={0},min2[6]={0};
int len = 85;//real = 85 , org = 461(460)
int base = 500;//651:b,1563:c ,, real = 0
int a[85]={0};
int max_buf[5] = {0};
int max_buf_val[5] = {0};
int box[250] ={0};
int box_len = 250;
int window = 50;
int window_cnt =0;
int max_temp=0;
int temp;
int ture=0;
float xinglv=0, time = 0.004 ,xinglv_jiange1=0,xinglv_jiange2=0;//time要按采样时间算
//从TXT中读250个数字
FILE *fpRead=fopen("box2.txt","r");//b,c ,, real = real_1
if(fpRead==NULL)
{
return 0;
}
for(i=0;i<box_len;i++)
{
fscanf(fpRead,"%d ",&box[i]);
//printf("%d ",a[i]);
}
//把250分成5个区间,取最大值
for(i=0;i<5;i++)
{
max_temp = 0;
for(j = i*window;j < i*window+window;j++)
{
max_temp=(max_temp>box[j])?max_temp:box[j];
if(max_temp==box[j])
{
max_buf[i]=j;
max_buf_val[i]=box[j];
}
}
window_cnt = window_cnt + 1;
}
//排序
for(i=0;i<5;i++)
{
for(j=i+1;j<5;j++)
{
if(max_buf_val[i]<max_buf_val[j])
{
temp=max_buf_val[i];
max_buf_val[i]=max_buf_val[j];
max_buf_val[j]=temp;
temp=0;
temp=max_buf[i];
max_buf[i]=max_buf[j];
max_buf[j]=temp;
}
}
}
for(i=0;i<5;i++)//计算有效的波峰
{
if(max_buf_val[i]>max_buf_val[0]-5) ture++;
}
//取前有效个,算qs
for(i=0;i<ture;i++)
{
for(j=max_buf[i];j<max_buf[i]+10;j++)
{
min1[i]=(min1[i]<box[i])?min1[i]:box[j];
if(min1[i]==box[j]) min1_piont[i]=j;//S
}
for(j=max_buf[i]-12;j<max_buf[i];j++)
{
min2[i]=(min2[i]<box[j])?min2[i]:box[j];
if(min2[i]==box[j]) min2_piont[i]=j;//R
}
}
//算心率,心律不齐
xinglv = 60/(((max_buf[1]-max_buf[0])+(max_buf[2]-max_buf[1]))/2*time); // (time)not have value !!! just test
xinglv_jiange1 = max_buf[1]-max_buf[0];
xinglv_jiange2 = max_buf[2]-max_buf[1];
//输出
printf(" %d %d %d %d %d , %d\n",max_buf[0],max_buf[1],max_buf[2],max_buf[3],max_buf[4],window_cnt);
printf(" %d %d %d %d %d , %d\n",max_buf_val[0],max_buf_val[1],max_buf_val[2],max_buf_val[3],max_buf_val[4],window_cnt);
printf(" R-R间距 %f %f \n",xinglv_jiange1,xinglv_jiange2);
printf(" 心率 %f 间隔误差 %f \n",xinglv,(max_buf[1]-max_buf[0])/(max_buf[2]-max_buf[1]));
for(i=0;i<ture;i++)
{
printf(" 输入%d个整数中Q%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,min2[i],min2_piont[i],min2_piont[i]+base);
printf(" 输入%d个整数中R%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,max_buf_val[i],max_buf[i],max_buf[i]+base);
printf(" 输入%d个整数中S%d是:%d \n其数组下标是:%d 是第:%d个\n",box_len,i,min1[i],min1_piont[i],min1_piont[i]+base);
}
ture = 0;
return 0;
}
结果对于处理过的数据还是比较准的
误差分析:
提示:还是需要处理两最大值采样点x坐标过近的问题,滤除可能的误差。