Created
July 5, 2013 06:47
-
-
Save ifq/5932464 to your computer and use it in GitHub Desktop.
根据脉搏电压数据检测心跳的程序
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* ifqqfi在gmail.com | |
* [2013-07-05 五] | |
* | |
* 脉搏检测程序 | |
*/ | |
#include <stdio.h> | |
#include <stdlib.h> | |
/* 临时这个么搞,读数据的缓冲区大小 */ | |
#define MAX_LEN 999999 | |
/* 每秒采样次数,根据实际系统的采样率调整 */ | |
#define SCAN_FREQ 78 | |
/* 快速射血期 的扫描次数 */ | |
#define QUICK_BLOOD_INJECT ((int)(SCAN_FREQ * 0.11)) | |
/* 检测到一次之后的跳跃点数 */ | |
#define JUMP_INTERVAL ((int)(SCAN_FREQ * 0.382)) | |
/* 过滤用的门限值 */ | |
#define THRESH_RATE (float)(1 - 0.618) | |
#define DBG_SW 1 | |
#ifdef DBG_SW | |
int cnt_diff_under = 0; | |
int cnt_range_under = 0; | |
#endif | |
/* 读取文件的buff */ | |
float alldata[MAX_LEN]; | |
int inline is_diff_peak(float *diff, int pos, float thr_max) | |
{ | |
float tmp; | |
float *iter; | |
int i; | |
if (*(diff + pos) < thr_max) { | |
#ifdef DBG_SW | |
cnt_diff_under++; | |
#endif | |
return 0; | |
} | |
iter = diff + pos - (int)(QUICK_BLOOD_INJECT / 2); | |
tmp = 0; | |
for (i = 0; i < QUICK_BLOOD_INJECT; ++i, ++iter) { | |
tmp += *iter; | |
} | |
tmp /= QUICK_BLOOD_INJECT; | |
if (tmp < thr_max) { | |
#ifdef DBG_SW | |
//printf ("pos =%d, tmp = %f\n", pos, tmp); | |
cnt_range_under++; | |
#endif | |
return 0; | |
} | |
return 1; | |
} | |
/* http://ifq.github.io */ | |
int rhythmcount(float *fifo , int len) | |
{ | |
int i; | |
float *diff; /* 导数缓冲区 */ | |
float dif_max=0; /* 导数最大值 */ | |
float thr_max; /* 导数阀值 */ | |
int j=0; | |
int k[1000]; /* 用于存放最大值位置,有多少心跳次数就用多少 */ | |
int rhythm; | |
float DR_R; /* 心跳间隔的采样点数品均值 */ | |
//printf ("len = %d\n", len); | |
diff = malloc(sizeof(float) * (len+2)); | |
if (!diff) { | |
perror("malloc fail\n"); | |
return (-1); | |
} | |
*diff=0; /* 头两个字节置0 */ | |
*(diff+1)=0; | |
/* 按DIFF(i)=f(i+1)-f(i-1)+2*f(i+2)-2*f(i-2)公式计算导数 */ | |
for (i=2;i<len-2;i++) | |
{ | |
*(diff+i) = (*(fifo+i+1)) + 2 * (*(fifo+i+2)) | |
- (*(fifo+i-1)) - 2 * (*(fifo+i-2)); | |
if ((dif_max) < *(diff+i)) { | |
dif_max=*(diff+i); | |
} | |
} | |
*(diff+len-1)=0; /* 置0 */ | |
*(diff+len)=0; | |
thr_max=dif_max * THRESH_RATE; //设定阈值 | |
#ifdef DBG_SW | |
printf ("max dif=%f, thr=%f\n", dif_max, thr_max); | |
#endif | |
/* 检测 */ | |
for (i = 1; i < len - 2; i++) | |
{ | |
if (is_diff_peak(diff, i, thr_max)) { | |
k[j++]=i; | |
i += JUMP_INTERVAL; | |
} | |
} | |
DR_R=(k[j-1]-k[0])/(float)(j-1); //计?算?R-R间?距¨¤ | |
printf ("dr_r %f, j=%d, gap=%d \n", DR_R, j, k[j-1]-k[0]); | |
rhythm=(len/DR_R); //通ª¡§过y公?式º?200*60/DR-R求¨®得Ì?心?率¨º值¦Ì | |
free(diff); | |
return rhythm; | |
} | |
/* ifqqfi */ | |
int main(int argc, char **argv) | |
{ | |
float tmp; | |
int reallen = 0; | |
int totlebeat; | |
float time; | |
if (argc < 3) { | |
printf ("argc not enough!\n"); | |
exit(-1); | |
} | |
time = atof(argv[2]); | |
FILE *fp = fopen(argv[1],"r"); | |
while (fscanf(fp, "%f", &tmp) != EOF) { | |
alldata[reallen++] = tmp > 255 ? 255 : tmp; | |
} | |
fclose(fp); | |
#if 0 | |
for (i = 0; i < reallen; ++i) { | |
printf ("%f\n", alldata[i]); | |
} | |
#endif | |
totlebeat = rhythmcount(alldata, reallen); | |
#ifdef DBG_SW | |
printf("dbg diff=%d, range=%d\n",cnt_diff_under, cnt_range_under); | |
#endif | |
/* http://iwood.co.nr */ | |
printf("total beat = %d, rate = %f\n", totlebeat, totlebeat/time); | |
return 0; | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment