Multi-Threading Face Detection with OpenCV

edited May 16 in Kinect

Hi All,

As the title suggests I'm trying to get face detection in real time which is too slow when executed directly in draw. Therefore I'd like to implement it within a Runnable class but I'm not having much luck. Can someone point me in the right direction?

Error:

You are trying to draw outside OpenGL's animation thread.
Place all drawing commands in the draw() function, or inside
your own functions as long as they are called from draw(),
but not in event handling functions such as keyPressed()
or mousePressed().
OpenGL error 1282 at top endDraw(): invalid operation
OpenGL error 1282 at bot endDraw(): invalid operation

Code:

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

Capture video;

OpenCV opencv;
Rectangle[] faces;
boolean detected = false;

FaceThread getFaces;

void setup() {
  size(640, 480);

  video = new Capture(this, width, height);

  faces = new Rectangle[0];

  getFaces = new FaceThread();

  video.start();
}

void draw() { 
  background(0);
  PImage img = video;
  img.filter(GRAY);
  image(img, 0, 0, 768, 432);

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

  if (millis() % 500 == 0) {
    println("starting thread"); 
    getFaces.start();
  }
}

void mousePressed() {
  println(frameRate);
}

PImage getCanvas(){
 return get(); 
}

class FaceThread implements Runnable {

  Thread thread;

  public FaceThread() {
  }

  public void start() {
    thread = new Thread(this);
    thread.start();
  }

  public void run() {
    println("New Thread");
    opencv.loadImage(getCanvas());
    faces = opencv.detect();    
    println(faces.length);
  }

  public void stop() {
    thread = null;
  }

  public void dispose() {
    stop();
  }
}
Tagged:

Answers

  • Just a cpl of suggestions if you want speed:

    1. Detect faces only every so other frame(s)
    2. Use a scale down version of your sketch.

    Kf

  • edited May 15

    Thanks for the suggestion unfortunately both 1 and 2 freeze the video stream for a short period which I'm really trying to avoid.

  • edited May 16

    Here's an updated "runnable" version of the code which seems close.

    Error:

    openCV Unknown exception in JNI code {objdetect::detectMultiScale_11()} 
    

    Code:

    import processing.video.*;
    import gab.opencv.*;
    import java.awt.Rectangle;
    
    Capture cam;
    
    OpenCV opencv;
    Rectangle[] faces;
    boolean detected = false;
    
    PImage incomingImage;
    
    int threads = 2;
    
    FaceThread[] runningThreads;
    
    void setup() {
      size(640, 480);
    
      cam = new Capture(this, 640, 480);
      cam.start();
    
      faces = new Rectangle[0];
    
      opencv = new OpenCV(this, 640, 480);
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);  
    
      incomingImage = createImage(width, height, RGB);
    
      runningThreads = new FaceThread [threads];
      for (int i = 0; i < threads; i++) {
        runningThreads[i] = new FaceThread(incomingImage);
      }
    }
    
    void draw() {
      background(0);
    
      if (cam.available() == true) {
        cam.read();
        incomingImage = cam;
    
        if (millis() > 5000) {
    
          for (int i = 0; i < threads; i++) {
    
            if (!runningThreads[i].running) { // If the thread is not busy then assign it a new frame
              runningThreads[i] = new FaceThread(incomingImage);
              runningThreads[i].start();
              break; 
            }
          }
        }
      }
    
      image(incomingImage, 0, 0, 768, 432);
    }
    
    void mousePressed() {
      println(frameRate);
    }
    
    class FaceThread implements Runnable {
    
      Thread thread;
      PImage imageToAnalyse;
      boolean running;
    
      public FaceThread(PImage incoming) {
        imageToAnalyse = incoming;
        running = false;
      }
    
      public void start() {
        running = true;
        thread = new Thread(this);
        thread.start();
      }
    
      public void run() {
        println("New Thread");
        opencv.loadImage(imageToAnalyse);
        faces = opencv.detect();    
        println("# of faces found: " + faces.length);
        dispose(); // We close the thread when it’s done
      }
    
      public void stop() {
        thread = null;
        running = false;
      }
    
      public void dispose() {
        stop();
      }
    }
    

    EDIT: Seems like it's unclear what parts of OpenCV are thread-safe

    How to make OpenCV Detect method thread-safe?

Sign In or Register to comment.