Batch Loading Images and Cropping

edited April 2016 in Kinect

Hello, I recently started working with processing and I have two questions that I really need help with.

The two things I need to accomplish are this:

  1. Load a folder of 1000 jpgs into processing.
  2. Spit out cropped images of their faces.

Currently I having trouble saving just what I copy. I only seem to save the entire window.

Rectangle[] faces;
int filenumber = 0;
int croppedimage = 0;

void setup() {
  opencv = new OpenCV(this, "test2.jpg");

  opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);  
  faces = opencv.detect();

  size(opencv.width, opencv.height);


}

void draw() {

  for (int i = 0; i < faces.length; i++) {
    rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
    copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);

  if (filenumber < 3) {
    line(filenumber, 0, filenumber, 100);
    filenumber = filenumber + 1;
    } else {
    noLoop();
  }
  //croppedimage = get(opencv.width*2,opencv.width*2, opencv.height, opencv.height);
  //image(croppedimage,0,0);
  saveFrame("cropped" + filenumber); 
}
  }

Answers

  • I do batch of images in IrfanView

    it's free and it's great

    also, please go back and format your code: 2 empty lines before, select code, click C in the small command bar

  • edited February 2015

    Sorry about that! Within IrfanView, I am not able to crop based on faces detected? That is why I am writing this program.

    To rephrase, how do can I save what I copy() into an image file.

  • PImage sectionOfScreen = get(0,0, faces[i].width, faces[i].height);
    
    sectionOfScreen.save(...................
    

    not tested.............

  • Wonderful! It worked perfectly... In the code below, once I have assigned the files to that string dir.list, can I pass them through what I just wrote? Then have the program run until all files have been cropped?

     File dir = new File("/Users/JPHS1/Documents/Processing/Park");
    String[] list = dir.list();
    
    if (list == null) {
      println("Folder does not exist or cannot be accessed.");
    } 
    else {
      println(list);
    } 
    
  • edited February 2015

    I think so

    think of your former sketch with setup() and draw() as the kernel

    around this kernel we want to build our new frame

    Rectangle[] faces;
    int filenumber = 0;
    int croppedimage = 0;
    
     void setup() {
        size(600.600);
        for (String name1 : list) {
           setupSmall(name1);
           drawSmall();
        }
        //  
    } 
    
    void draw() {
         // empty 
    }
    

    as you guessed, put the stuff of setup and draw in setupSmall and drawSmall

    and then proceed

    void setupSmall(String name1) {
      opencv = new OpenCV(this, name1);
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); 
      faces = opencv.detect();
    
    }    
    
    
    void drawSmall() {
    
      for (int i = 0; i < faces.length; i++) {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop();
      }
      //croppedimage = get(opencv.width*2,opencv.width*2, opencv.height, opencv.height);
      //image(croppedimage,0,0);
      saveFrame("cropped" + filenumber);
    }
      }
    

    not tested

    [EDITED]

    Chrisir ;-)

  • edited February 2015

    I definitely see what you are saying and I understand, but I do not understand how you can have two void setups and two void draws? Are you saying that my 'kernel' should reference the setupSmall and drawSmall?

    import gab.opencv.*;
    import java.awt.Rectangle;
    
    OpenCV opencv;
    Rectangle[] faces;
    int filenumber = 0;
    int croppedimage = 0;
    
     void setup() {
        size(600.600);
        for (String name1 : list) {
     void setupSmall(String name1);{
       opencv = new OpenCV(this, name1);
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE); 
      faces = opencv.detect();
     }    
      void drawSmall();{
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop();
      }
    
      saveFrame("cropped" + filenumber);
    }
        }
        //  
    } 
    
    void draw() {
         // empty 
    }
    
  • edited February 2015
    import gab.opencv.*;
    import java.awt.Rectangle;
    
    OpenCV opencv;
    Rectangle[] faces;
    int filenumber = 0;
    int croppedimage = 0;
    
     void setup() {
        size(600.600);
        for (String name1 : list) {
           setupSmall(name1);
           drawSmall();
        }
        // 
    } 
    
    void draw() {
         // empty
    }
    
    // -----------------------------------------
    
     void setupSmall(String name1) {
       opencv = new OpenCV(this, name1);
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
      faces = opencv.detect();
     }   
    
      void drawSmall() {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop(); // ??????????????????????????
      } // else 
    
      saveFrame("cropped" + filenumber);
    } // function 
    
  • something like this

    from setup you call setupSmall and drawSmall

  • edited February 2015

    sorry, I'm off now

    I corrected my posts

  • for (String name1 : list) {

    "name1" is where i will place the string I created from my folder of jpgs, but what does "list" identify?

  • Deleted your last message, since you made a separate thread from it. Avoid duplicates. (But making a new thread for a new problem is a good idea.)

  • Didn't this work?

    for (String name1 : list) {
    

    It should work.

    What it does:

    for (int i=0; i<list.length; i++) {
        String name1 = list[i];
        // .........
    }
    

    list is the same array as in your sketch.....

    ;-)

  • I had to change name1 to the string that holds the file names, correct? And when I do so, it gives me a NullPointerException. PhilLho had said that I needed to supply OpenCV with the full file path.

    image

  • I had to change name1 to the string that holds the file names, correct?

    that's my line:

    String name1 = list[i];
    

    it depends on what list holds (names of files?)

    anyway, when all images are in the same folder

    String name1 = "c:/win/here/" + list[i];
    

    or when the in the data folder of your sketch

    String name1 = dataPath("") + list[i];
    

    ;-)

  • I am sadly still having trouble. I keep receiving a NullPointerException on "for(String name1: imglist)"

    For clarification, I am attempting to access a folder of jpgs.

    import gab.opencv.*;
    import java.awt.Rectangle;
    
    OpenCV opencv;
    Rectangle[] faces;
    int filenumber = 0;
    int croppedimage = 0;
    
    File dir = new File("/Users/JPHS1/Downloads/timelapse");
    String[] imglist = dir.list();
    
    
     void setup() {
    
        for (String name1 : imglist) {
           setupSmall(name1);
           drawSmall();
        }
        // 
    } 
    
    void draw() {
         // empty
    }
    
    // -----------------------------------------
    
     void setupSmall(String name1) {
    
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
      faces = opencv.detect();
     }   
    
      void drawSmall() {
        for (int i = 0; i < faces.length; i++) {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop(); // ??????????????????????????
     }
    
      PImage sectionOfScreen = get(0,0, faces[i].width, faces[i].height);
    
    sectionOfScreen.save("cropped" + filenumber);
    
    }
      }
    
  • Also, Chrisir

    for (String name1 : list) {

    List is not any type of predetermined function in processing?

  • Hello!

    Sorry, I don't know what you are asking at the moment.

    As I said, list is the name of an array that you came up with in the first place:

    File dir = new File("/Users/JPHS1/Documents/Processing/Park");
    String[] list = dir.list();
    

    see above.

    this:

    for (String name1 : list) {
    

    is just a short way to write a for-loop. Sorry, I didn't mean to confuse you with that.

    here is an example sketch to show this new for (String var : list) approach :

    String[] list = {
      "what", "ever", "is", "here"
    };
    
    for (String temp : list) {
      println (temp);
    }
    

    that's the same as

    String[] list = {
      "what", "ever", "is", "here"
    };
    
    for (int i=0; i < list.length; i++) {
      String temp = list [i];
      println (temp);
    }
    

    so, just use that to loop to all the files you got in your list (add the path somehow).

    during the loop call setupSmall and and drawSmall as described.

    Please ask again if you need help.

    Chrisir ;-)

  • edited February 2015

    You are amazing, and thank you so much for your help. Just to clarify, here is where I am at with my code. I have two sections.

    Section #1 : Works perfectly on ONE image, whatever "test.jpg" is.

    import gab.opencv.*;
    import java.awt.Rectangle;
    OpenCV opencv;
    Rectangle[] faces;
    
    int filenumber = 0;
    int croppedimage = 0;
    
    void setup() {
      opencv = new OpenCV(this, "test.jpg");
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);  
      faces = opencv.detect();
    
      size(opencv.width, opencv.height);
    
    
    }
    
    void draw() {
    
      for (int i = 0; i < faces.length; i++) {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop();
      }
      PImage sectionOfScreen = get(0,0, faces[i].width, faces[i].height);
    
    sectionOfScreen.save("cropped" + filenumber);
      }
    }
    

    Section #2 : Implementing loop

    PImage[] fragment;
    int n=20;
    
    void setup() {
     size(400, 400);
     fragment=new PImage[n];
     for(int i=1;i<fragment.length;i++){
     fragment[i]=loadImage(str(i) + ".jpg");
    

    So now i have fragment[i] storing the files. How can I properly move this loop into the code in section 1? I believe I would then have a working application. I may also need to get the full file paths instead of just the names.

  • edited February 2015

    ok, it's good to break the problem down into 2 independent sections

    first the path question:

    does this work:

    PImage[] fragment;
    int n=20;
    
    void setup() {
     size(400, 400);
     frameRate(3); 
     fragment=new PImage[n];
     for(int i=1;i<fragment.length;i++) 
     {
     fragment[i]=loadImage(str(i) + ".jpg");
     image( fragment[i],0,0);
    
    }
    }
    

    ?

  • edited February 2015

    when it works, path is ok.

    you should see 20 images come up

  • edited February 2015

    now for the joining of the sections

    I answered that a few times but never mind

    import gab.opencv.*;
    import java.awt.Rectangle;
    
    OpenCV opencv;
    Rectangle[] faces;
    int filenumber = 0;
    int croppedimage = 0;
    
    
     void setup() {
        size(600, 600);
    
        for(int i=1;i<fragment.length;i++) {
           String name1 = str(i) + ".jpg"; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           setupSmall(name1);
           drawSmall();
        }
        // 
    } 
    
    void draw() {
         // empty
    }
    
    // -----------------------------------------
    
     void setupSmall(String name1) {
       opencv = new OpenCV(this, name1);
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
      faces = opencv.detect();
     }   
    
      void drawSmall() {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop(); // ??????????????????????????
      } // else 
    
      saveFrame("cropped" + filenumber);
    } // function 
    
  • edited February 2015

    Well it appears to work, but when I println(fragment[i]);it outputs this

    processing.core.PImage@80e4ee
    processing.core.PImage@452d0297
    processing.core.PImage@e052afc
    processing.core.PImage@6f9e0e7b
    

    It also does not display any images.

  • it totally doesn't work

    what does it say in the direct window...?

    do you have the 20 images in data folder of your sketch as 1.jpg, 2.jpg etc.?

  • Damn.. I think I got it. Well, you got it, but I hit run.

    import gab.opencv.*;
    import java.awt.Rectangle;
    
    OpenCV opencv;
    Rectangle[] faces;
    PImage[] fragment;
    int filenumber = 0;
    int croppedimage = 0;
    int nof = 100; 
    
     void setup() {
        size(600, 600);
        fragment=new PImage[nof];
    
        for(int i=1;i<fragment.length;i++) {
           String name1 = str(i) + ".jpg"; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
           setupSmall(name1);
           drawSmall();
        }
        // 
    } 
    
    void draw() {
         // empty
    }
    
    // -----------------------------------------
    
     void setupSmall(String name1) {
       opencv = new OpenCV(this, name1);
    
      opencv.loadCascade(OpenCV.CASCADE_FRONTALFACE);
      faces = opencv.detect();
     }   
    
      void drawSmall() {
         for (int i = 0; i < faces.length; i++) {
        rect(faces[i].x, faces[i].y, faces[i].width, faces[i].height);
        copy(opencv.getInput(),faces[i].x, faces[i].y, faces[i].width, faces[i].height, 0,0, faces[i].width, faces[i].height);
    
      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop(); // ??????????????????????????
      } // else 
    
    PImage sectionOfScreen = get(0,0, faces[i].width, faces[i].height);
    
    sectionOfScreen.save("cropped" + filenumber);
    
      }
      }
    
  • It is extremely inaccurate though, haha. OpenCV's face detection is not too hot. It recognized a hub cap, also my code makes it think that it has to output and image for everything, not only when it detects a 'face'.

  • here...........

    //
    //states 
    final int stateWaitForFolder = 0;  // consts  
    final int stateReadImages    = 1;
    final int stateMain          = 2;
    int state = stateWaitForFolder;  // current
    
    String folderGlobal = "";  
    String[] strList; 
    PImage[] imgList;
    
    void setup() {
      size (1100, 700); 
      selectFolder("Select a folder to process:", "folderSelected");
    }
    
    void draw() {
      // 
      switch (state) {
    
      case stateWaitForFolder:
    
        // waiting until folder has been selected 
        if (!folderGlobal.equals("")) {
          println (folderGlobal);
    
          File f = dataFile(folderGlobal);
          strList = f.list();
          println ("found " + strList.length);
          imgList = new PImage [ strList.length ];
          int i = 0;
          for (String imageName : strList) {
            if (imageName.indexOf(".JPG")>-1 ||
              imageName.indexOf(".jpg")>-1) {
              println(imageName);
              imgList[i] = loadImage (folderGlobal+"/"+imageName);
              // image (imgList[i], i*60, 0);
              i++;
            } // if
          } // for 
          state = stateReadImages; //  next state
        } // if 
        break;
    
      case stateReadImages:    
        // int length1 = strList.length;
        int i = 0; 
        for (PImage image1 : imgList) {
          if (image1!=null) {
            image(image1, i, 0);
            i+=30;
          } // if
        } // for
        state = stateMain; //  next 
        break;
    
      case stateMain:
        // 
        break;
    
      default:
        // 
        println ("error 91"); 
        exit();
        break;
        //
      }  // switch
      //
    }  // func 
    
    // ------------------------------------------
    // file handling 
    
    void folderSelected(File selection) {
      if (selection == null) {
        println("Window was closed or the user hit cancel.");
      } 
      else {
        println("User selected " + selection.getAbsolutePath());
        folderGlobal = selection.getAbsolutePath();
      } // else
    }
    //
    
  • Wonderful... now just to find a way to integrate this.

  • just replace line 50 with

       String name1 = str(i) + ".jpg"; // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       setupSmall(name1);
       drawSmall();
    
  • edited February 2015

    what is this?

      if (filenumber < 3) {
        line(filenumber, 0, filenumber, 100);
        filenumber = filenumber + 1;
        } else {
        noLoop(); // ??????????????????????????
      } // else 
    

    wouldn't that be enough

    filenumber = filenumber + 1;

  • Yes you are quite right about the simplification of that loop. I will implement the two together now.

Sign In or Register to comment.