2014-12-05 70 views
4

我想创建一个应用程序,可以使用您的计算机摄像头检测心跳。我工作的代码,因为2周,并开发此代码,在这里我得到迄今使用WebCam检测心跳?

它是如何工作的?如下图所示...

  1. 使用OpenCV的
  2. 获取前额的图像
  3. 应用过滤器将其转换成灰度图像[你可以跳过]
  4. 查找每绿色pixle的平均强度检测脸框架
  5. 保存的平均值为Array
  6. 应用FFT(我用微量库)提取从FFT频谱心脏的跳动(在这里,我需要一些帮助)

在这里,我需要帮助从FFT频谱中提取心跳。谁能帮我。 Here,是在python中开发的类似的应用程序,但我不能低估这个代码,所以我正在开发相同的程序。任何人都可以帮助我了解这个Python代码中提取心跳的部分。

//---------import required ilbrary ----------- 
import gab.opencv.*; 
import processing.video.*; 
import java.awt.*; 
import java.util.*; 
import ddf.minim.analysis.*; 
import ddf.minim.*; 
//----------create objects--------------------------------- 
Capture video; // camera object 
OpenCV opencv; // opencv object 
Minim  minim; 
FFT   fft; 
//IIRFilter filt; 
//--------- Create ArrayList-------------------------------- 
ArrayList<Float> poop = new ArrayList(); 
float[] sample; 
int bufferSize = 128; 
int sampleRate = 512; 
int bandWidth = 20; 
int centerFreq = 80; 
//--------------------------------------------------- 
void setup() { 
    size(640, 480); // size of the window 
    minim = new Minim(this); 
    fft = new FFT(bufferSize, sampleRate); 
    video = new Capture(this, 640/2, 480/2); // initializing video object 
    opencv = new OpenCV(this, 640/2, 480/2); // initializing opencv object 
    opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); // loading haar cscade file for face detection 
    video.start(); // start video 
} 

void draw() { 
    background(0); 
    // image(video, 0, 0); // show video in the background 
    opencv.loadImage(video); 
    Rectangle[] faces = opencv.detect(); 
    video.loadPixels(); 
    //------------ Finding faces in the video ----------- 
    float gavg = 0; 
    for (int i = 0; i < faces.length; i++) { 
    noFill(); 
    stroke(#FFB700); // yellow rectangle 
    rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); // creating rectangle around the face (YELLOW) 
    stroke(#0070FF); //blue rectangle 
    rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height-2*faces[i].height/3); // creating a blue rectangle around the forehead 
    //-------------------- storing forehead white rectangle part into an image ------------------- 
    stroke(0, 255, 255); 
    rect(faces[i].x+faces[i].width/2-15, faces[i].y+15, 30, 15); 
    PImage img = video.get(faces[i].x+faces[i].width/2-15, faces[i].y+15, 30, 15); // storing the forehead aera into a image 
    img.loadPixels(); 
    img.filter(GRAY); // converting capture image rgb to gray 
    img.updatePixels(); 

    int numPixels = img.width*img.height; 
    for (int px = 0; px < numPixels; px++) { // For each pixel in the video frame... 
     final color c = img.pixels[px]; 
     final color luminG = c>>010 & 0xFF; 
     final float luminRangeG = luminG/255.0; 
     gavg = gavg + luminRangeG; 
    } 

    //-------------------------------------------------------- 
    gavg = gavg/numPixels; 
    if (poop.size()< bufferSize) { 
     poop.add(gavg); 
    } 
    else poop.remove(0); 
    } 
    sample = new float[poop.size()]; 
    for (int i=0;i<poop.size();i++) { 
    Float f = (float) poop.get(i); 
    sample[i] = f; 
    } 

    if (sample.length>=bufferSize) { 
    //fft.window(FFT.NONE); 
    fft.forward(sample, 0); 
    // bpf = new BandPass(centerFreq, bandwidth, sampleRate); 
    // in.addEffect(bpf); 
    float bw = fft.getBandWidth(); // returns the width of each frequency band in the spectrum (in Hz). 
    println(bw); // returns 21.5332031 Hz for spectrum [0] & [512] 

    for (int i = 0; i < fft.specSize(); i++) 
    { 
     // println(" Freq" + max(sample)); 
     stroke(0, 255, 0); 
     float x = map(i, 0, fft.specSize(), 0, width); 
     line(x, height, x, height - fft.getBand(i)*100); 
    // text("FFT FREQ " + fft.getFreq(i), width/2-100, 10*(i+1)); 
    // text("FFT BAND " + fft.getBand(i), width/2+100, 10*(i+1)); 
    } 
    } 
    else { 
    println(sample.length + " " + poop.size()); 
    } 
} 

void captureEvent(Capture c) { 
    c.read(); 
} 
+0

这家伙脉冲太高的人只是坐在那里......如何裸/讨厌贝贝 – GPPK 2014-12-05 07:15:55

+0

@depends是他在看... – Spektre 2015-02-09 15:30:10

回答

1

将FFT应用于具有128个样本的窗口中。

int bufferSize = 128;

在绘制方法中,采样被存储在一个数组中,直到填充要应用FFT的缓冲区。之后,缓冲区保持满。要插入新的样本,最旧的将被删除。 gavg是平均灰色通道颜色。

gavg = gavg/numPixels; 
if (poop.size()< bufferSize) { 
    poop.add(gavg); 
} 
else poop.remove(0); 

应对船尾采样

sample = new float[poop.size()]; 
for (int i=0;i < poop.size();i++) { 
    Float f = (float) poop.get(i); 
    sample[i] = f; 
} 

现在是可能应用FFT到样本阵列

fft.forward(sample, 0); 

在代码中只显示频谱结果。必须计算心跳频率。 对于fft中的每个频段,您必须找到最大值,并且该位置是心跳频率。

for(int i = 0; i < fft.specSize(); i++) 
     { // draw the line for frequency band i, scaling it up a bit so we can see it 
      heartBeatFrequency = max(heartBeatFrequency,fft.getBand(i)); 
     } 

然后得到的带宽要知道的频率。

float bw = fft.getBandWidth(); 

调整频率。

heartBeatFrequency = fft。getBandWidth()* heartBeatFrequency;

+0

嗨大卫,感谢您的善意回复,并阐述我的代码。我已添加您在帖子末尾提到的建议代码片段。当我运行代码时,它给了我“无穷大”,请告诉我为什么会发生这种情况?再次感谢:) – Ryder 2014-12-06 15:58:56

+0

你解决了吗? fft.getBandWidth(),heartBeatFrequency其中的一个具有无限的价值。验证heartBeatFrequency是否用-infinity初始化,如果fft.getBandWidth()返回一个有效值,不同的是无穷大。 – 2014-12-09 13:34:54