原理
简单介绍一下,网上可以查到很多关于手机测心率的这种项目,大概就是: 把手指放在摄像头和闪光灯上,通过手指处脉搏跳动充血导致的细微颜色变化来确定心跳波动,确定波峰波谷,根据两个波峰之间的时间差来确定瞬时心率。
思路
首先,采集视频流,根据拿到的RGB颜色转成HSV颜色集,其实我们只用到了HSV的H。
对拿到的H进行一些处理,看跟人喜好或者具体情况,主要是用于后面的折线图和计算瞬时心率,如果有能力的话可以处理一下噪音数据,因为可能测的时候手指轻微抖动会造成一些不稳定的数据。
根据处理后的H就可以进行画折线图了,我是把处理后的H和时间戳进行了绑定,用来后面的计算心率。
根据处理后的H来确定波峰波谷,利用两个波谷之间的时间差计算心率。
实现
大致思路就是上面这样,下面来看一下代码具体实现以下。
1.首先我先初始化了一些数据,方便后面使用
// 设备
@property (strong, nonatomic) AVCaptureDevice *device;
// 结合输入输出
@property (strong, nonatomic) AVCaptureSession *session;
// 输入设备
@property (strong, nonatomic) AVCaptureDeviceInput *input;
// 输出设备
@property (strong, nonatomic) AVCaptureVideoDataOutput *output;
// 输出的所有点
@property (strong, nonatomic) NSMutableArray *points;
// 记录浮点变化的前一次的值
static float lastH = 0;
// 用于判断是否是第一个福点值
static int count = 0;
// 初始化
self.device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
self.session = [[AVCaptureSession alloc]init];
self.input = [[AVCaptureDeviceInput alloc]initWithDevice:self.device error:nil];
self.output = [[AVCaptureVideoDataOutput alloc]init];
self.points = [[NSMutableArray alloc]init];
2.设置视频采集流,为了节省内存,我没有输出视频画面
// 开启闪光灯
if ([self.device isTorchModeSupported:AVCaptureTorchModeOn]) {
[self.device lockForConfiguration:nil];
// 开启闪光灯
self.device.torchMode=AVCaptureTorchModeOn;
// 调低闪光灯亮度(为了减少内存占用和避免时间长手机发烫)
[self.device setTorchModeOnWithLevel:0.01 error:nil];
[self.device unlockForConfiguration];
}
// 开始配置input output
[self.session beginConfiguration];
// 设置像素输出格式
NSNumber *BGRA32Format = [NSNumber numberWithInt:kCVPixelFormatType_32BGRA];
NSDictionary *setting =@{(id)kCVPixelBufferPixelFormatTypeKey:BGRA32Format};
[self.output setVideoSettings:setting];
// 抛弃延迟的帧
[self.output setAlwaysDiscardsLateVideoFrames:YES];
//开启摄像头采集图像输出的子线程
dispatch_queue_t outputQueue = dispatch_queue_create("VideoDataOutputQueue", DISPATCH_QUEUE_SERIAL);
// 设置子线程执行代理方法
[self.output setSampleBufferDelegate:self queue:outputQueue];
// 向session添加
if ([self.session canAddInput:self.input]) [self.session addInput:self.input];
if ([self.session canAddOutput:self.output]) [self.session addOutput:self.output];
// 降低分辨率,减少采样率(为了减少内存占用)
self.session.sessionPreset = AVCaptureSessionPreset1280x720;
// 设置最小的视频帧输出间隔
self.device.activeVideoMinFrameDuration = CMTimeMake(1, 10);
// 用当前的output 初始化connection
AVCaptureConnection *connection =[self.output connectionWithMediaType:AVMediaTypeVideo];
[connection setVideoOrientation:AVCaptureVideoOrientationPortrait];
// 完成编辑
[self.session commitConfiguration];
// 开始运行
[self.session startRunning];










