Face detection - OpenCV: If clauses to act when no face is detected - HELP PLEASE!

edited September 7 in Kinect

Hi there,

I'm working on a face detection code that will put a square around your face when its detected, but will display text or an image when no face is detected on screen. Ideally I'd like it to respond after a couple of second of no detection but anything is better than nothing!

I currently have the face detection code working. But when trying to add an if clause for null faces make an action - it doesn't work when I run the code - any help is greatly appreciated.

Here is the current code:

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

Capture cam; OpenCV opencv; Rectangle[] faces;

void setup() { size(640, 480, P2D); background (0, 0, 0); cam = new Capture( this, 640, 480, 30); cam.start(); opencv = new OpenCV(this, cam.width, cam.height); opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); }

void draw() { opencv.loadImage(cam); faces = opencv.detect(); image(cam, 0, 0); if (faces!=null) { for (int i=0; i< faces.length; i++) { noFill(); stroke(255, 255, 0); strokeWeight(10); rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); } } if (faces == null) { textAlign(CENTER); fill(255, 0, 0); textSize(56); text("UNDETECTED", 100, 100); } }

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

Answers

  • Edit post, highlight code, press ctrl-o to format.

    Please don't post duplicates.

  • edited September 8 Answer ✓
    import gab.opencv.*; 
    import processing.video.*; 
    import java.awt.Rectangle;
    
    Capture cam; 
    OpenCV opencv; 
    Rectangle[] faces;
    
    void setup() { 
      size(640, 480); 
      background (0, 0, 0); 
      cam = new Capture( this, 640, 480, 30); 
      cam.start(); 
      opencv = new OpenCV(this, cam.width, cam.height); 
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
    }
    
    void draw() { 
      opencv.loadImage(cam); 
      faces = opencv.detect(); 
      image(cam, 0, 0); 
    
      if (faces!=null) { 
        for (int i=0; i< faces.length; i++) { 
          noFill(); 
          stroke(255, 255, 0); 
          strokeWeight(10); 
          rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        }
      } 
      if (faces.length<=0) { 
        textAlign(CENTER); 
        fill(255, 0, 0); 
        textSize(56); 
        println("no faces");
        text("UNDETECTED", 200, 100);
      }
    }
    
    void captureEvent(Capture cam) { 
      cam.read();
    }
    

    Checked and the above works and does what you need.

  • edited September 7

    Your check for faces having a length of less than or equal to zero (Which is already a little weird because an array won't have a negative length...) on line 31 is INSIDE the check that faces isn't null on line 23. That is, the if condition on line 31 is really checking that the faces array is not null but is of 0 length. So which is it? If there are no faces detected, your values for faces will be null, right?

    I think what you really want is an ELSE statement:

    void draw() { 
      opencv.loadImage(cam); 
      faces = opencv.detect(); 
      image(cam, 0, 0); 
    
      if (faces!=null) { // Are there faces?
        for (int i=0; i< faces.length; i++) { // Yes! There are faces! For each face...
          noFill(); 
          stroke(255, 255, 0); 
          strokeWeight(10); 
          rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); // Denote it.
        }
      } else { // Otherwise there are no faces!
        textAlign(CENTER); 
        fill(255, 0, 0); 
        textSize(56); 
        //println("no faces"); // Avoid println() inside draw(), even conditionally!
        text("UNDETECTED", 200, 100); // Declare no faces are seen.
      } // We are done with both YES FACES and NO FACES sections here.
    
    } // This is the end of draw().
    

    A few stray comments will help your code make more sense! Always throw yourself a few hints for later!

  •   if (faces!=null) { 
        ...
      } 
      if (faces.length<=0) { 
    

    and if faces were null?

  • edited September 8

    @tfguy44 that code doesn't work, if you cover up face you get nothing rather than the text being displayed. This was Emily original problem. It should work right but it doesn't. edit: also i'm NOT checking line 31 inside the loop of line 23 at all. and <=0 is just habit failsafe code, of course an array cant be less than 0 but you know..it doesnt hurt in the check.

    @koogs if faces=null then faces.length is blatantly 0 and therefore this works. edit. i mean faces = empty aka no face. edit: faces is never null anymore thanks to faces=opencv.detect();

  • Apologies @koogs only my second post in the forum so got a bit confused about etiquette and how some discussions get flagged as questions and some didn't. I know for next time thanks!

  • @ashleyjamesbrown major thank you!!! Works perfectly!

  • if faces=null then faces.length is blatantly 0 and therefore this works.

    If faces is null then trying to trying to access faces.length will get you a null pointer exception

  • edited September 7

    @ashleyjamesbrown -- re:

    if faces=null then faces.length is blatantly 0 and therefore this works.

    No.

    Just set faces to null and see what your code does in this sketch:

    import java.awt.Rectangle;
    Rectangle[] faces;
    
    faces=null;
    
    if (faces!=null) { 
      println("faces!=null");  
    } 
    if (faces.length<=0) { 
      println("faces.length<=0");
    }
    

    "Null pointer access."

    Or just:

    import java.awt.Rectangle;
    Rectangle[] faces;
    
    faces=null;
    println(faces.length);
    

    "Null pointer access."

  • edited September 8

    post edit:

    @koogs unless the array has been initialised. @jeremydouglas yes thats correct if you haven't called opencv to init the faces array before doing that.

    Both of you - My wording is incorrect about where I was referring. I meant faces = empty aka no face.

    If there are no faces then the array is 0. Its no longer null in the draw because its been initialised by the line faces = opencv.detect(); This is why you cant run an else or if _faces = null _ in the draw method because the array is no longer null, its just empty and therefore this statement will never evaluate.

  • import gab.opencv.*; 
    import processing.video.*; 
    import java.awt.Rectangle;
    
    Capture cam; 
    OpenCV opencv; 
    Rectangle[] faces;
    
    void setup() { 
      size(640, 480); 
      background (0, 0, 0); 
      cam = new Capture( this, 640, 480, 30); 
      cam.start(); 
      opencv = new OpenCV(this, cam.width, cam.height); 
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
      faces = null; // yeh ok set it to null if you like
    }
    
    void draw() { 
      opencv.loadImage(cam); 
      faces = opencv.detect(); //init the faces array - its now no longer null
      println(faces.length); // gives 0
      image(cam, 0, 0); 
    
      if (faces!=null) { 
        for (int i=0; i< faces.length; i++) { 
          noFill(); 
          stroke(255, 255, 0); 
          strokeWeight(10); 
          rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        }
      } 
      if (faces.length<=0) { 
        textAlign(CENTER); 
        fill(255, 0, 0); 
        textSize(56); 
        println("no faces");
        text("UNDETECTED", 200, 100);
      }
    }
    
    void captureEvent(Capture cam) { 
      cam.read();
    }
    
Sign In or Register to comment.