iOS利用手机摄像头测心率

2020-01-17 21:54:12丽君

这里我降低了闪光灯亮度,降低了分辨率,减少了每秒钟输出的帧。主要就是为了减少内存的占用。(我手里只有一台6,没有测其他设备可不可以)

3.在output的代理方法中采集视频流


// captureOutput->当前output  sampleBuffer->样本缓冲  connection->捕获连接
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

  //获取图层缓冲
  CVPixelBufferRef imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
  CVPixelBufferLockBaseAddress(imageBuffer, 0);
  uint8_t*buf = (uint8_t *)CVPixelBufferGetBaseAddress(imageBuffer);
  size_t bytesPerRow = CVPixelBufferGetBytesPerRow(imageBuffer);
  size_t width = CVPixelBufferGetWidth(imageBuffer);
  size_t height = CVPixelBufferGetHeight(imageBuffer);

  float r = 0, g = 0,b = 0;
  float h,s,v;
  // 计算RGB
  TORGB(buf, width, height, bytesPerRow, &r, &g, &b);
  // RGB转HSV
  RGBtoHSV(r, g, b, &h, &s, &v);
  // 获取当前时间戳(精确到毫秒)
  double t = [[NSDate date] timeIntervalSince1970]*1000;
  // 返回处理后的浮点值
  float p = HeartRate(h);
  // 绑定浮点和时间戳
  NSDictionary *point = @{[NSNumber numberWithDouble:t]:[NSNumber numberWithFloat:p]};
  //下面按个人情况可以进行计算心率或者画心率图
}

到这里数据已经处理好了,后面可以根据数据画折线图,或者计算心率

计算RGB


void TORGB (uint8_t *buf, float ww, float hh, size_t pr, float *r, float *g, float *b) {
  float wh = (float)(ww * hh );
  for(int y = 0; y < hh; y++) {
    for(int x = 0; x < ww * 4; x += 4) {
      *b += buf[x];
      *g += buf[x+1];
      *r += buf[x+2];
    }
    buf += pr;
  }
  *r /= 255 * wh;
  *g /= 255 * wh;
  *b /= 255 * wh;
}

RGB转HSV


void RGBtoHSV( float r, float g, float b, float *h, float *s, float *v ) {
  float min, max, delta;
  min = MIN( r, MIN(g, b ));
  max = MAX( r, MAX(g, b ));
  *v = max;
  delta = max - min;
  if( max != 0 )
    *s = delta / max;
  else {
    *s = 0;
    *h = -1;
    return;
  }
  if( r == max )
    *h = ( g - b ) / delta;
  else if( g == max )
    *h = 2 + (b - r) / delta;
  else
    *h = 4 + (r - g) / delta;
  *h *= 60;
  if( *h < 0 )
    *h += 360;
}

根据h处理浮点


float HeartRate (float h) {
  float low = 0;
  count++;
  lastH = (count==1)?h:lastH;
  low = (h-lastH);
  lastH = h;
  return low;
}

4.分析数据,计算心率

这里我纠结了好长时间,试了几种不同的方法,都没有一个比较理想的结果,计算出来的特别不准。后来看了 http://www.easck.com/88158/ 这篇文章,后面优化的部分有一个 基音算法 ,虽不明,但觉厉,对此表示非常感谢。吼吼吼。