2013-07-18 99 views
3

我正在嘗試對我正在嘗試的簡單遊戲執行人臉跟蹤。我正在處理它。使用卡爾曼濾波與OpenCV和處理進行人臉跟蹤

我用OpenCV做簡單的人臉檢測,使用Haar Cascades。但是,隨着時間的推移順利追蹤臉部會出現問題。此外,它不檢測傾斜的臉。

對於一些Google-ing,我發現我必須實現卡爾曼濾波器來平滑人臉跟蹤。但是,這是我第一次聽說卡爾曼濾波器,而且我很難實現它。

我在處理使用這個庫的OpenCV:https://github.com/atduskgreg/opencv-processing

如果有人能告訴我如何實現卡爾曼與處理或Java(因爲這個庫是基於Java API)過濾器,這將是非常很有幫助。

這是我用於人臉檢測的代碼。這是從庫中實例的草圖中的一個:

import gab.opencv.*; 
import processing.video.*; 
import java.awt.*; 

Capture video; 
OpenCV opencv; 

void setup() { 
    size(640, 480); 
    video = new Capture(this, 640/2, 480/2); 
    opencv = new OpenCV(this, 640/2, 480/2); 
    opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); 

    video.start(); 
} 

void draw() { 
    background(255); 
    scale(2); 
    opencv.loadImage(video); 

    image(video, 0, 0); 

    noFill(); 
    stroke(0, 255, 0); 
    strokeWeight(3); 
    Rectangle[] faces = opencv.detect(); 
    println(faces.length); 

    for (int i = 0; i < faces.length; i++) { 
    println(faces[i].x + "," + faces[i].y); 
    rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); 
    } 
} 

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

http://stackoverflow.com/questions/15678585/how-to-smooth-the-tracking-in-camshift/15683124#15683124 – William

+0

@William,是的,當我在搜索時遇到了這個問題。但我無法將代碼移植到Processing。 – Shrihari

回答

0

我沒有設法端口卡爾曼濾波器C++樣品威廉鏈接到,因爲不是所有的從C++ API函數存在於OpenCV的Java包裝,所以這是據我已經有了:

import gab.opencv.*; 
import processing.video.*; 
import java.awt.*; 

import org.opencv.core.*; 
import org.opencv.video.*; 

int w = 640; 
int h = 480; 
int hw = w/2; 
int hh = h/2; 

Capture video; 
OpenCV opencv; 

/* 
Mat img(500, 500, CV_8UC3); 
KalmanFilter KF(4, 2, 0); 
Mat_<float> state(4, 1); // (x, y, Vx, Vy) 
Mat processNoise(4, 1, CV_32F); 
Mat_<float> measurement(2,1); measurement.setTo(Scalar(0)); 
*/ 
Mat img; 
KalmanFilter KF; 
Mat processNoise; 
MatOfFloat state,measurement; 

void setup() { 
    size(w, h); 
    video = new Capture(this, hw, hh); 
    opencv = new OpenCV(this, hw, hh); 
    opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); 
    video.start(); 

    img = new Mat(w,h,CvType.CV_8UC3); 
    KF = new KalmanFilter(4,2,0,CvType.CV_32F); 
    state = new MatOfFloat(4,1); 
} 

void draw() { 
    background(255); 
    scale(2); 
    opencv.loadImage(video); 

    image(video, 0, 0); 

    noFill(); 
    stroke(0, 255, 0); 
    strokeWeight(3); 
    Rectangle[] faces = opencv.detect(); 
    if(faces.length > 0) 
    rect(faces[0].x,faces[0].y,faces[0].width,faces[0].height); 
} 

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

你可能注意到了,我沒有得到很遠,像statePretransitionMatrix性質是不可見的。

雖然不一樣,也許有點平均可能會有所幫助:

import gab.opencv.*; 
import processing.video.*; 
import java.awt.*; 

int w = 640; 
int h = 480; 
int hw = w/2; 
int hh = h/2; 

Capture video; 
OpenCV opencv; 

int historySize = 10; 
Rectangle[] history; 

void setup() { 
    size(w, h); 
    video = new Capture(this, hw, hh); 
    opencv = new OpenCV(this, hw, hh); 
    opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); 
    video.start(); 
    setupHistory(); 
} 
void setupHistory(){ 
    history = new Rectangle[historySize]; 
    for(int i = 0 ; i < historySize ; i++) history[i] = new Rectangle(); 
} 
void keyPressed(){ 
    if(key == 'h' && historySize > 1) { 
    noLoop(); 
    historySize--; 
    setupHistory(); 
    loop(); 
    } 
    if(key == 'H') { 
    noLoop(); 
    historySize++; 
    setupHistory(); 
    loop(); 
    } 
    println(historySize); 
} 

void draw() { 
    background(255); 
    scale(2); 
    opencv.loadImage(video); 

    image(video, 0, 0); 

    noFill(); 
    stroke(0, 255, 0); 
    strokeWeight(3); 
    Rectangle[] faces = opencv.detect(); 
    if(faces.length > 0){ 
    Rectangle f = mousePressed ? average(faces[0]) : faces[0]; 
    rect(f.x,f.y,f.width,f.height); 
    } 
} 

void captureEvent(Capture c) { 
    c.read(); 
} 
Rectangle average(Rectangle newFace){ 
    Rectangle avg = new Rectangle(); 
    for(int i = historySize - 1; i > 0; i--){ 
    history[i] = history[i-1]; 
    avg.x += history[i].x; 
    avg.y += history[i].y; 
    avg.width += history[i].width; 
    avg.height += history[i].height; 
    } 
    history[0] = newFace; 
    avg.x += history[0].x; 
    avg.y += history[0].y; 
    avg.width += history[0].width; 
    avg.height += history[0].height; 
    avg.x /= historySize; 
    avg.y /= historySize; 
    avg.width /= historySize; 
    avg.height /= historySize; 
    return avg; 
} 

按住按下看到流暢的結果鼠標。使用H鍵增加,使用h減小歷史記錄大小。