Get biggest face from openCV

edited December 2017 in Kinect

Hello,

This is my first post on this forum, and i'm in need of your help. I'm working on a project with an android that has a set of animatronic eyes and a facetracking feature. I'm using the opencv library and Processing 3.3.6 to execute the tracking, and an arduino t control the eyes. At the moment i've created a script where the eyes are following only ONE face, but sometimes the eyes 'jump' when a new face enters the webcam. I would like to avoid this, so my reasoning was to always get the biggest width of the faces detected and send the x and y coordinates to the arduino. I found similar questions on the forum to 'Get the largest element from an array' but although i understand the logic my sketch keeps on outputting all sets of x and y coordinates detected. A supplementary note is in place that i work heuristically with code and have very basic knowledge of programming languages. Any push in the right direction is highly appreciated. Below the processing code:

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

    Capture video;
    OpenCV opencv;
    Serial myPort;  // Create object from Serial class

    int newXpos, newYpos;
    //These variables hold the x and y location for the middle of the detected face
    int midFaceX = 0;
    int midFaceY = 0;

    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);  

     //println(Serial.list()); // List COM-ports (Use this to figure out which port the Arduino is connected to)
      String portName = Serial.list()[1];
      //select first com-port from the list (change the number in the [] if your sketch fails to connect to the Arduino)
      myPort = new Serial(this, portName, 19200);   //Baud rate is set to 19200 to match the Arduino baud rate.

      video.start();
    }


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

      image(video, 0, 0 );

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

      int maxValueFace = 0;
      int maxIndex = -1;

      for (int i = 0; i < faces.length; i++ ) {

        if (faces[i].width > maxValueFace) {
          maxIndex = i;
          maxValueFace = faces[i].width;
          //println(maxValueFace);

        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); //
        midFaceX = faces[i].x + (faces[i].width/2); // middle of the face
        midFaceY = faces[i].y + (faces[i].height/2); // middle of the face
        float xpos = map(midFaceX, 0, width, 90, 120); //maps range of servos L->R
        float ypos = map(midFaceY, 0, height, 90, 120); //maps range of servos U->D
        int newXpos = (int)xpos; //converts position X float into integer
        int newYpos = (int)ypos; //converts position Y float into integer
        myPort.write(newXpos+"x"); // send X coordinate to Arduino
        myPort.write(newYpos+"y"); // send Y coordinate to Arduino
        println(midFaceX + "," + midFaceY);
        }
      }
    }

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

Answers

  • Use a separate loop for finding the max, remember the index.

    The block starting at line 51 then needs moving outside the loop and should just use the remembered index.

  • edited December 2017

    Thank you for your response, i'm struggling my way through it bit by bit. I've placed from 51 line onward in a separate loop like this:

    for (int i = 0; i < faces.length; i++ ) {
    
        if (faces[i].width > maxValueFace) {
          maxIndex = i;
          maxValueFace = faces[i].width;
          println(maxIndex);
        }
         if (maxIndex > -1); {
    
            rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height); //
            midFaceX = faces[i].x + (faces[i].width/2); // middle of the face
            midFaceY = faces[i].y + (faces[i].height/2); // middle of the face
            float xpos = map(midFaceX, 0, width, 20, 120); //maps range of servos L->R
            float ypos = map(midFaceY, 0, height, 20, 120); //maps range of servos U->D
            int newXpos = (int)xpos; //converts position X float into integer
            int newYpos = (int)ypos; //converts position Y float into integer
            myPort.write(newXpos+"x"); // send X coordinate to Arduino
            myPort.write(newYpos+"y"); // send Y coordinate to Arduino
            println(midFaceX + "," + midFaceY);
          }  
      }
    

    Still no success. If I comment out from line 51 onward and print the 'maxIndex' it still prints multiple numbers when multiple faces are detected. Is there something incorrect in the way i've set up the max declaration?

  • Answer ✓

    lines 8 to 20 are STILL within the loop (which runs from line 1 to the end)

Sign In or Register to comment.