最近一直在搞R波检测算法,对OSEA代码主要是对注释做一个翻译,增加注释,使代码更容易理解。

一、首先看QRSDE.H

/*****************************************************************************
FILE:  qrsdet.h
AUTHOR: Patrick S. Hamilton
REVISED:    4/16/2002___________________________________________________________________________qrsdet.h QRS detector parameter definitions
Copywrite (C) 2000 Patrick S. HamiltonThis file is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.This software is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU Library General Public License for more
details.You should have received a copy of the GNU Library General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.You may contact the author by e-mail (pat@eplimited.com) or postal mail
(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
MA 02143 USA).  For updates to this software, please visit our website
(http://www.eplimited.com).__________________________________________________________________________Revisions:4/16: Modified to allow simplified modification of digital filters inqrsfilt().
*****************************************************************************/#define SAMPLE_RATE   200 /* Sample rate in Hz. */
#define MS_PER_SAMPLE   ( (double) 1000/ (double) SAMPLE_RATE)
#define MS10    ((int) (10/ MS_PER_SAMPLE + 0.5))
#define MS25    ((int) (25/MS_PER_SAMPLE + 0.5))
#define MS30    ((int) (30/MS_PER_SAMPLE + 0.5))
#define MS80    ((int) (80/MS_PER_SAMPLE + 0.5))
#define MS95    ((int) (95/MS_PER_SAMPLE + 0.5))
#define MS100   ((int) (100/MS_PER_SAMPLE + 0.5))
#define MS125   ((int) (125/MS_PER_SAMPLE + 0.5))
#define MS150   ((int) (150/MS_PER_SAMPLE + 0.5))
#define MS160   ((int) (160/MS_PER_SAMPLE + 0.5))
#define MS175   ((int) (175/MS_PER_SAMPLE + 0.5))
#define MS195   ((int) (195/MS_PER_SAMPLE + 0.5))
#define MS200   ((int) (200/MS_PER_SAMPLE + 0.5))
#define MS220   ((int) (220/MS_PER_SAMPLE + 0.5))
#define MS250   ((int) (250/MS_PER_SAMPLE + 0.5))
#define MS300   ((int) (300/MS_PER_SAMPLE + 0.5))
#define MS360   ((int) (360/MS_PER_SAMPLE + 0.5))
#define MS450   ((int) (450/MS_PER_SAMPLE + 0.5))
#define MS1000  SAMPLE_RATE
#define MS1500  ((int) (1500/MS_PER_SAMPLE))
#define DERIV_LENGTH    MS10
#define LPBUFFER_LGTH ((int) (2*MS25))
#define HPBUFFER_LGTH MS125#define WINDOW_WIDTH MS80            // Moving window integration width.
#define FILTER_DELAY (int) (((double) DERIV_LENGTH/2) + ((double) LPBUFFER_LGTH/2 - 1) + (((double) HPBUFFER_LGTH-1)/2) + PRE_BLANK)  // filter delays plus 200 ms blanking delay 过滤器的延迟加200毫秒消隐延迟
#define DER_DELAY   WINDOW_WIDTH + FILTER_DELAY + MS100

二、QRSDET2.CPP

/*****************************************************************************
FILE:  qrsdet2.cpp
AUTHOR: Patrick S. Hamilton
REVISED:    7/08/2002___________________________________________________________________________qrsdet2.cpp: A QRS detector.
Copywrite (C) 2002 Patrick S. HamiltonThis file is free software; you can redistribute it and/or modify it under
the terms of the GNU Library General Public License as published by the Free
Software Foundation; either version 2 of the License, or (at your option) any
later version.This software is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.  See the GNU Library General Public License for more
details.You should have received a copy of the GNU Library General Public License along
with this library; if not, write to the Free Software Foundation, Inc., 59
Temple Place - Suite 330, Boston, MA 02111-1307, USA.You may contact the author by e-mail (pat@eplimited.edu) or postal mail
(Patrick Hamilton, E.P. Limited, 35 Medford St., Suite 204 Somerville,
MA 02143 USA).  For updates to this software, please visit our website
(http://www.eplimited.com).__________________________________________________________________________This file contains functions for detecting QRS complexes in an ECG.  The
QRS detector requires filter functions in qrsfilt.cpp and parameter
definitions in qrsdet.h.  QRSDet is the only function that needs to be
visable outside of these files.Syntax:int QRSDet(int ecgSample, int init) ;Description:QRSDet() implements a modified version of the QRS detectionalgorithm described in:Hamilton, Tompkins, W. J., "Quantitative investigation of QRSdetection rules using the MIT/BIH arrhythmia database",IEEE Trans. Biomed. Eng., BME-33, pp. 1158-1165, 1987.Consecutive ECG samples are passed to QRSDet.  QRSDet wasdesigned for a 200 Hz sample rate.  QRSDet contains a numberof static variables that it uses to adapt to different ECGsignals.  These variables can be reset by passing any valuenot equal to 0 in init.Note: QRSDet() requires filters in QRSFilt.cppReturns:When a QRS complex is detected QRSDet returns the detection delay.****************************************************************/#include <mem.h>       /* For memmov. */
#include <math.h>
#include "qrsdet.h"#define PRE_BLANK  MS195
#define MIN_PEAK_AMP    7 // Prevents detections of peaks smaller than 150 uV.// External Prototypes.int QRSFilter(int datum, int init) ;
int deriv1( int x0, int init ) ;// Local Prototypes.int Peak( int datum, int init ) ;
int mean(int *array, int datnum) ;
int thresh(int qmean, int nmean) ;
int BLSCheck(int *dBuf,int dbPtr,int *maxder) ;double TH = .3125 ;int DDBuffer[DER_DELAY], DDPtr ; /* Buffer holding derivative data. */
int Dly  = 0 ;const int MEMMOVELEN = 7*sizeof(int);int QRSDet( int datum, int init ){static int det_thresh, qpkcnt = 0 ;static int qrsbuf[8], noise[8], rrbuf[8] ;static int rsetBuff[8], rsetCount = 0 ;static int nmean, qmean, rrmean ;static int count, sbpeak = 0, sbloc, sbcount = MS1500 ;static int maxder, lastmax ;static int initBlank, initMax ;static int preBlankCnt, tempPeak ;int fdatum, QrsDelay = 0 ;int i, newPeak, aPeak ;/*    Initialize all buffers to 0 on the first call.  */if( init ){for(i = 0; i < 8; ++i){noise[i] = 0 ;   /* Initialize noise buffer */rrbuf[i] = MS1000 ;/* and R-to-R interval buffer. */}qpkcnt = maxder = lastmax = count = sbpeak = 0 ;initBlank = initMax = preBlankCnt = DDPtr = 0 ;sbcount = MS1500 ;QRSFilter(0,1) ;  /* initialize filters. */Peak(0,1) ;}fdatum = QRSFilter(datum,0) ; /* Filter data. 滤波*//* Wait until normal detector is ready before calling early detections. */
   /* 直到正常检测器准备好了之后开始早起检测。此处我理解的是等到心电波形稳定之后开始采集。 */

aPeak = Peak(fdatum,0) ;if(aPeak < MIN_PEAK_AMP)aPeak = 0 ;// Hold any peak that is detected for 200 ms// in case a bigger one comes along. There// can only be one QRS complex in any 200 ms window./**/保存200ms内所有的波峰,以防止后面出现更大的波峰,只所以这样,是因为我们认为前后200ms内只能有一个QRS波。*/newPeak = 0 ;if(aPeak && !preBlankCnt) // If there has been no peak for 200 ms,save this one and start counting.
{ // 如果在一个波峰之后200ms内没有波峰,则保存这个波峰并开始计数。tempPeak = aPeak ;preBlankCnt = PRE_BLANK ; // MS200}else if(!aPeak && preBlankCnt) // If we have held onto a peak for{ // 200 ms pass it on for evaluation.if(--preBlankCnt == 0)//如果我们保存了一个波峰后过了200ms的检测依然没有检测到新的符合条件的波峰,newPeak = tempPeak ; //则认为这个波峰为新的QRS波        }else if(aPeak) // If we were holding a peak, but{ // this ones bigger, save it andif(aPeak > tempPeak) // start counting to 200 ms again.{// 如果我们检测出一个波峰,并且比以前的最大波峰还大,则保存下来重新开始计数。tempPeak = aPeak ;preBlankCnt = PRE_BLANK ; // MS200}else if(--preBlankCnt == 0)newPeak = tempPeak ;}/* Save derivative of raw signal for T-wave and baseline shift discrimination.

     * 保存原始信号的导数用于识别T波和基线漂移
 */

DDBuffer[DDPtr] = deriv1( datum, 0 ) ;if(++DDPtr == DER_DELAY)DDPtr = 0 ;/* Initialize the qrs peak buffer with the first eight *//* local maximum peaks detected. */if( qpkcnt < 8 ){++count ;if(newPeak > 0) count = WINDOW_WIDTH ;if(++initBlank == MS1000){initBlank = 0 ;qrsbuf[qpkcnt] = initMax ;initMax = 0 ;++qpkcnt ;if(qpkcnt == 8){qmean = mean( qrsbuf, 8 ) ;nmean = 0 ;rrmean = MS1000 ;sbcount = MS1500+MS150 ;det_thresh = thresh(qmean,nmean) ;}}if( newPeak > initMax )initMax = newPeak ;}else /* Else test for a qrs. */{++count ;if(newPeak > 0){/* Check for maximum derivative and matching minima and maxima for T-wave and baseline shift rejection. Only consider this peak if it doesn't seem to be a base line shift. */ if(!BLSCheck(DDBuffer, DDPtr, &maxder)){// Classify the beat as a QRS complex// if the peak is larger than the detection threshold.if(newPeak > det_thresh){memmove(&qrsbuf[1], qrsbuf, MEMMOVELEN) ;qrsbuf[0] = newPeak ;qmean = mean(qrsbuf,8) ;det_thresh = thresh(qmean,nmean) ;memmove(&rrbuf[1], rrbuf, MEMMOVELEN) ;rrbuf[0] = count - WINDOW_WIDTH ;rrmean = mean(rrbuf,8) ;sbcount = rrmean + (rrmean >> 1) + WINDOW_WIDTH ;count = WINDOW_WIDTH ;sbpeak = 0 ;lastmax = maxder ;maxder = 0 ;QrsDelay = WINDOW_WIDTH + FILTER_DELAY ;initBlank = initMax = rsetCount = 0 ;}// If a peak isn't a QRS update noise buffer and estimate.// Store the peak for possible search back.else{memmove(&noise[1],noise,MEMMOVELEN) ;noise[0] = newPeak ;nmean = mean(noise,8) ;det_thresh = thresh(qmean,nmean) ;// Don't include early peaks (which might be T-waves)// in the search back process. A T-wave can mask// a small following QRS.if((newPeak > sbpeak) && ((count-WINDOW_WIDTH) >= MS360)){sbpeak = newPeak ;sbloc = count - WINDOW_WIDTH ;}}}}/* Test for search back condition. If a QRS is found in *//* search back update the QRS buffer and det_thresh. */if((count > sbcount) && (sbpeak > (det_thresh >> 1))){memmove(&qrsbuf[1],qrsbuf,MEMMOVELEN) ;qrsbuf[0] = sbpeak ;qmean = mean(qrsbuf,8) ;det_thresh = thresh(qmean,nmean) ;memmove(&rrbuf[1],rrbuf,MEMMOVELEN) ;rrbuf[0] = sbloc ;rrmean = mean(rrbuf,8) ;sbcount = rrmean + (rrmean >> 1) + WINDOW_WIDTH ;QrsDelay = count = count - sbloc ;QrsDelay += FILTER_DELAY ;sbpeak = 0 ;lastmax = maxder ;maxder = 0 ;initBlank = initMax = rsetCount = 0 ;}}// In the background estimate threshold to replace adaptive threshold// if eight seconds elapses without a QRS detection.if( qpkcnt == 8 ){if(++initBlank == MS1000){initBlank = 0 ;rsetBuff[rsetCount] = initMax ;initMax = 0 ;++rsetCount ;// Reset threshold if it has been 8 seconds without// a detection.if(rsetCount == 8){for(i = 0; i < 8; ++i){qrsbuf[i] = rsetBuff[i] ;noise[i] = 0 ;}qmean = mean( rsetBuff, 8 ) ;nmean = 0 ;rrmean = MS1000 ;sbcount = MS1500+MS150 ;det_thresh = thresh(qmean,nmean) ;initBlank = initMax = rsetCount = 0 ;}}if( newPeak > initMax )initMax = newPeak ;}return(QrsDelay) ;}/*************************************************************** peak() takes a datum as input and returns a peak height* when the signal returns to half its peak height, or **************************************************************/int Peak( int datum, int init ){static int max = 0, timeSinceMax = 0, lastDatum ;int pk = 0 ;if(init)max = timeSinceMax = 0 ;if(timeSinceMax > 0)++timeSinceMax ;if((datum > lastDatum) && (datum > max)){max = datum ;if(max > 2)timeSinceMax = 1 ;}else if(datum < (max >> 1)){pk = max ;max = 0 ;timeSinceMax = 0 ;Dly = 0 ;}else if(timeSinceMax > MS95){pk = max ;max = 0 ;timeSinceMax = 0 ;Dly = 3 ;}lastDatum = datum ;return(pk) ;}/********************************************************************mean returns the mean of an array of integers. It uses a slowsort algorithm, but these arrays are small, so it hardly matters.********************************************************************/int mean(int *array, int datnum){long sum ;int i ;for(i = 0, sum = 0; i < datnum; ++i)sum += array[i] ;sum /= datnum ;return(sum) ;}/**************************************************************************** thresh() calculates the detection threshold from the qrs mean and noise mean estimates.****************************************************************************/int thresh(int qmean, int nmean){int thrsh, dmed ;double temp ;dmed = qmean - nmean ;/* thrsh = nmean + (dmed>>2) + (dmed>>3) + (dmed>>4); */temp = dmed ;temp *= TH ;dmed = temp ;thrsh = nmean + dmed ; /* dmed * THRESHOLD */return(thrsh) ;}/***********************************************************************BLSCheck() reviews data to see if a baseline shift has occurred.This is done by looking for both positive and negative slopes ofroughly the same magnitude in a 220 ms window.***********************************************************************/int BLSCheck(int *dBuf,int dbPtr,int *maxder){int max, min, maxt, mint, t, x ;max = min = 0 ;for(t = 0; t < MS220; ++t){x = dBuf[dbPtr] ;if(x > max){maxt = t ;max = x ;}else if(x < min){mint = t ;min = x;}if(++dbPtr == DER_DELAY)dbPtr = 0 ;}*maxder = max ;min = -min ;/* Possible beat if a maximum and minimum pair are foundwhere the interval between them is less than 150 ms. */ if((max > (min>>3)) && (min > (max>>3)) &&(abs(maxt - mint) < MS150))return(0) ;elsereturn(1) ;}

转载于:https://my.oschina.net/waleswood/blog/348297

OSEA中QRS波检测算法代码分析-未完待续相关推荐

  1. OSEA中QRS波检测算法

    当信号经过滤波等预处理后,检测器开始检测任何一个峰值,这峰包括信号中的所有峰值.每次检测到一个峰值,它被分类为QRS波,或者噪声,或者为了后来的分类保存它.算法利用峰值的高度,相对于上一个QRS波的位 ...

  2. QRS波检测算法集锦(含源代码)

    下面介绍一些我找到的一些QRS波检测算法的公开源代码 1:Pantompkin[1985年] 2:Filter-Bank[1999年] 3:Phase Space[1999年] 4:RST State ...

  3. 用python做归结演绎推理_Python中惯用的一些操作总结(未完待续)

    Python中常用的一些操作总结(未完待续) 写在前面的话 其实也没有什么可以写的,或者说完全没有价值.因为你只要动一动手指就可以在Google上找到我要写的这些东西.只是我还不习惯好久没有碰我的bl ...

  4. Python中常用的一些操作总结(未完待续)update @ 2017-5-18

    写在前面的话 其实也没有什么可以写的,或者说完全没有价值.因为你只要动一动手指就可以在Google上找到我要写的这些东西.只是我还不习惯好久没有碰我的blog,但是我又不想写没有价值的东西.或许有价值 ...

  5. [Python]从哪里开始学习写代码(未完待续)

    预警:这只是我在学习中的一点感受,可能并不完全准确,也不包括面向对象编程的思想(我还不太懂),也有水文的嫌疑,大佬请温和批评指正或者绕道. 计算机语言 语言,是用来交流的.计算机是不能直接听懂人的语言 ...

  6. python编程思维代码_Python编程快速上手——强口令检测算法案例分析

    本文实例讲述了Python强口令检测算法.分享给大家供大家参考,具体如下: 强口令检测 题目如下: 写一个函数,它使用正则表达式,确保传入的口令字符串是强口令.强口令定义:长度不少于8个字符,同时包含 ...

  7. 计算机视觉子方向,计算机视觉方向简介 | 人脸识别中的活体检测算法综述

    原标题:计算机视觉方向简介 | 人脸识别中的活体检测算法综述 本文转载自"SIGAI人工智能学习与实践平台"(ID:SIGAICN) 导言 1. 什么是活体检测? 判断捕捉到的人脸 ...

  8. 人脸识别中的活体检测算法

    人脸识别中的活体检测算法综述 1. 什么是活体检测? 判断捕捉到的人脸是真实人脸,还是伪造的人脸攻击(如:彩色纸张打印人脸图,电子设备屏幕中的人脸数字图像 以及 面具 等) 2. 为什么需要活体检测? ...

  9. Yolov1目标检测算法详细分析

    Yolov1目标检测算法详细分析 Yolov1介绍 这是继RCNN,fast-RCNN 和 faster-RCNN之后,rbg(Ross Girshick)大神挂名的又一大作,起了一个很娱乐化的名字: ...

最新文章

  1. 超过efficientnet
  2. 批量提取文件创建时间_批量采集新浪微博用户内容
  3. InputStreamReader 和 OutputStreamWriter类使用方法简单介绍,及演示。
  4. 密码与安全新技术总结
  5. 算法提高 理财计划(java)
  6. linux cp 隐藏文件,如何用cp复制包含隐藏文件和隐藏目录及其内容?
  7. 【Elasticsearch】为什么我在Elasticsearch集群中看到大量的拒绝?
  8. python,web框架说明
  9. 更轻松的获取APK文件安装时间
  10. ASP.NET Using 的几种用法
  11. 小米8SE如何安装google框架-之 chrome 手机安装 没有可安装该应用的设备
  12. 查看oracle客户端的版本,Oracle客户端版本及位数(Windows系统)查看方法
  13. Win10重装系统后,Microsoft账号无法登录,提示“发生了错误”,以及输入账户密码后,显示白屏问题的解决方案
  14. 非系统盘根目录出现Msdia80.dll文件如何处理
  15. 华为手机USB调试与Log
  16. 小学计算机社团团长职责,社团团长小学作文
  17. 如何解决MathType公式与文字不在同一行问题---已解决
  18. 如何在Word中的项目符号列表中自定义项目符号
  19. css3 新属性的兼容性之--transform
  20. ai人工智能将替代人类_只有人工智能才能将我们从假货世界中拯救出来(人工智能也在创造世界)...

热门文章

  1. 遍历HashMap源码——红黑树原理、HashMap红黑树实现与反树型化(三)
  2. 直播教育平台源码中的人人分销是什么?如何实现?
  3. CRMEB 单商户系统,配置人人分销之后,在分销员管理列表中不显示推广员
  4. CSS使图片变模糊,亲测非常好用
  5. 数据库原理(十 四)- 数据库的实施和维护
  6. Company Meeting
  7. MySQL——统计函数count,合计函数sum,(avg,max,min)函数
  8. 对联写作精解心得(2)
  9. 红外测温 AGM8833红外热像仪传感器的使用
  10. 普通空调智能节能控制-红外人联