Blob find contours

edited April 2017 in Kinect

Hello everyone, I'm using this code:

https://github.com/atduskgreg/opencv-processing/blob/master/examples/FindContours/FindContours.pde

I wish by pressing the button B the contour which found, will reset and becomes ready for a new image.

import g4p_controls.*;
import java.awt.Font;
import gab.opencv.*;

PImage src, dst;
OpenCV opencv;

ArrayList<Contour> contours;
ArrayList<Contour> polygons;

GButton btnFilterA;
boolean filterA=false;

GButton btnFilterB;
boolean filterB=false;

void setup() {
  src = loadImage("1.jpg"); 
  size(1024, 768);
  opencv = new OpenCV(this, src);

  btnFilterA = new GButton(this, 600, 20, 140, 20);
  btnFilterA.setText("Go");
  btnFilterA.setLocalColorScheme(GCScheme.GREEN_SCHEME);

  btnFilterB = new GButton(this, 750, 20, 140, 20);
  btnFilterB.setText("Stop");
  btnFilterB.setLocalColorScheme(GCScheme.GREEN_SCHEME);

  //opencv.gray();
  //opencv.threshold(70);
  //dst = opencv.getOutput();

  contours = opencv.findContours();
  println("found " + contours.size() + " contours");
}

void draw() {
  //scale(0.5);
  image(src, 0, 0);
  //image(dst, src.width, 0);

  noFill();
  strokeWeight(3);

  for (Contour contour : contours) {

    beginShape();
    for (PVector point : contour.getPolygonApproximation().getPoints()) {
    if (filterA==true){
    stroke(0, 255, 0);
    contour.draw();
    stroke(255, 0, 0);
    vertex(point.x, point.y); 

    }
    endShape();
  }
}
}

public void handleButtonEvents(GButton button, GEvent event) {

  if (button == btnFilterA) {
     filterA=true;
  }
    if (button == btnFilterB) {
     contour.clear();

  }
  }

I tried with my code but even if off the contour remains in "memory" of the contour, how I can fix?

thanks

Answers

  • Notice your endShape is not in the same scope as your beginShape. Move line 57 one curly bracket out.

    To test if the array is being cleared out, try this:

    void mouseReleased(){
      println("Found " + contours.size() + " contours");
      contours.clear();
      println("Now found " + contours.size() + " contours");
    }
    

    In your code, line 68, you should be calling contours and not contour. This is what I disagree naming variables and containers following classes names. Very easy to create a bug and hard to track them. I will suggest spicing the names of your objects. It will make them more maintainable at the end as well.

    Kf

  • Thanks kfrajer for your help, I have corrected the error (contours) but I have not understand where to enter endShape();

    new code is:

    import g4p_controls.*;
    import java.awt.Font;
    import gab.opencv.*;
    
    OpenCV opencv;
    
    ArrayList<Contour> contours;
    ArrayList<Contour> polygons;
    
    PImage canvas;
    
    
    GButton btnFilterO;
    
    boolean filterO=false;
    
    
    void setup() {
      opencv = new OpenCV(this, canvas);
      contours = opencv.findContours();
    
    
    
      btnFilterO = new GButton(this, 180, 20, 140, 20);
      btnFilterO.setText("Open file");
      btnFilterO.setLocalColorScheme(GCScheme.GREEN_SCHEME);
    
    
      noFill();
    
    }
    
    void settings() {
    
      selectInput("Please select canvas picture:", "selectImage");
      while (canvas == null)  delay(100);
      size(canvas.width, canvas.height);
      noSmooth();
    
    }
    
    void draw() {
      background(canvas);
      loadPixels();
      canvas.loadPixels();
      canvas.updatePixels();
      strokeWeight(5);
    
      for (Contour contour : contours) {
    
        stroke(0, 255, 0);
        contour.draw();
        stroke(255, 0, 0);
        beginShape();
    
        for (PVector point : contour.getPolygonApproximation().getPoints()) {
        vertex(point.x, point.y); 
       }     
       endShape();
        }
    
      }
    
    
    
    void selectImage(final File f) {
      if (f == null || f.isDirectory()) {
    
        println("Window was closed or you've hit cancel.\n");
        System.exit(0);
      }
    
      final String canvasPath = f.getPath();
      println(canvasPath);
    
      if ((canvas = loadImage(canvasPath)) == null) {
        println("is an invalid image file. Try again...\n");
        selectInput("Please select canvas picture:", "selectImage");
    
      }
     }
    
    public void handleButtonEvents(GButton button, GEvent event) {
    
    
        if (button == btnFilterO) {
    
         selectInput("Please select canvas picture:", "selectImage"); 
      }
    
    }
    
    void mouseReleased(){
      println("Found " + contours.size() + " contours");
      contours.clear();
      println("Now found " + contours.size() + " contours");
    }
    

    every time I open a new file, it do not see the new contour, how can I fix?

    thanks

  • Right. If you post the code in the Processing IDE (aka. not here), select all your code and hit ctrl+T. This will autoformat your code. Then if you check the scope of beginShape and endShape, they are not under the same block aka. under the same curling bracket block.

    Kf

  • Ok, I also would recommend changing the way you are defining your size as you first image defines the size of your canvas. Instead, start with a pre-defined size and then when you load the image, you resize it. As it is right now for example, when I open a second image, if it is not the same size as the first image, it will throw an error.

    Also I do not think it is a good approach to call your selectImage() recursively.

    I will do instead (pseudo-code and not tested)

    Kf

    //Global field
    boolean requestImageStage=false;
    
    void selectImage(final File f) {
      if (f == null || f.isDirectory()) {
    
        println("Window was closed or you've hit cancel.\n");
        System.exit(0);
      }
    
      final String canvasPath = f.getPath();
      println(canvasPath);
      canvas = loadImage(canvasPath); 
      requestImageStage=false;  //Completed
      contours.clear();   //// REMOVE any previous contours as new image loaded!
    
      if(canvas!=null){
        //THIS is assuming you fixed your settings as I mentioned above
         canvas.resize(width,height);  
      }
     } 
    

    and it draw():

    void draw(){
     if (canvas == null && requestImageStage!=true) {
    
        background(0);
        println("is an invalid image file. Try again...\n");
        requestImageStage=true;
        selectInput("Please select canvas picture:", "selectImage"); 
      }
      else{
        background(canvas);
      }
    
      ....REST of the code omitted 
    
    }
    
  • edited April 2017

    Now I try, thank you!

  • I have tried all your advice and this is the code:

    import g4p_controls.*;
    import java.awt.Font;
    import gab.opencv.*;
    
    
    
    
    OpenCV opencv;
    
    ArrayList<Contour> contours;
    ArrayList<Contour> polygons;
    
    PImage canvas;
    float ratio;
    int n = 1;
    
    
    
    GButton btnFilterO;
    
    boolean filterO=false;
    boolean requestImageStage=false;
    
    
    
    
    void setup() {
      opencv = new OpenCV(this, canvas);
      contours = opencv.findContours();
    
      btnFilterO = new GButton(this, 180, 20, 140, 20);
      btnFilterO.setText("Open file");
      btnFilterO.setLocalColorScheme(GCScheme.GREEN_SCHEME);
    
      noFill();
    }
    
    void settings() {
    
      selectInput("Please select canvas picture:", "selectImage");
      while (canvas == null)  delay(100);
      size(canvas.width, canvas.height);
    
      noSmooth();
    }
    
    void draw() {
      if (canvas == null && requestImageStage!=true) {
    
        background(0);
        println("is an invalid image file. Try again...\n");
        requestImageStage=true;
        selectInput("Please select canvas picture:", "selectImage");
      } else {
        background(canvas);
        loadPixels();
        canvas.loadPixels();
        canvas.updatePixels();
        strokeWeight(5);
      }
    
    
      for (Contour contour : contours) {
    
        stroke(0, 255, 0);
        contour.draw();
        stroke(255, 0, 0);
        beginShape();
    
        for (PVector point : contour.getPolygonApproximation().getPoints()) {
          vertex(point.x, point.y);
        }
        endShape();
      }
    }
    
    
    void selectImage(final File f) {
      if (f == null || f.isDirectory()) {
    
        println("Window was closed or you've hit cancel.\n");
        System.exit(0);
      }
    
      final String canvasPath = f.getPath();
      println(canvasPath);
      canvas = loadImage(canvasPath); 
      requestImageStage=false;  //Completed
      contours.clear();   //// REMOVE any previous contours as new image loaded!
    
      if (canvas!=null) {
        //THIS is assuming you fixed your settings as I mentioned above
        canvas.resize(width, height);
      }
    } 
    
    public void handleButtonEvents(GButton button, GEvent event) {
    
    
      if (button == btnFilterO) {
    
        selectInput("Please select canvas picture:", "selectImage");
      }
    }
    

    but when I open the new image does not work detention of the contour, it works only the first time, I have this error:

    ConcurrentModificationException for (Contour contour : contours) {

    maybe I wrong something?

    thanks

  • This works.

    Kf

    import g4p_controls.*;
    import java.awt.Font;
    import gab.opencv.*;
    
    OpenCV opencv;
    
    ArrayList<Contour> contours;
    ArrayList<Contour> polygons;
    
    PImage canvas;
    float ratio;
    int n = 1;
    
    GButton btnFilterO;
    
    boolean filterO=false;
    boolean requestImageStage=false;
    
    
    void setup() {
      size(960, 720);
    
      //surface.setResizable(true);
      btnFilterO = new GButton(this, 180, 20, 140, 20);
      btnFilterO.setText("Open file");
      btnFilterO.setLocalColorScheme(GCScheme.GREEN_SCHEME);
    
      noFill();
      noSmooth();
      strokeWeight(5);
    }
    
    
    void draw() {
      if (canvas == null ) {
        if (requestImageStage!=true) {
          background(0);
          requestImageStage=true;
          selectInput("Please select canvas picture:", "selectImage");
        }
      } else {
    
        if (requestImageStage==true) {
          //surface.setSize(canvas.width, canvas.height);
          canvas.resize(width, height);
    
          opencv = new OpenCV(this, canvas);
          contours = opencv.findContours();
          requestImageStage=false;
        } else {
    
    
          background(canvas);
          loadPixels();
          canvas.loadPixels();
    
    
          for (Contour contour : contours) {
    
            stroke(0, 255, 0);
            contour.draw();
            stroke(255, 0, 0);
            beginShape();
            for (PVector point : contour.getPolygonApproximation().getPoints()) {
              vertex(point.x, point.y);
            }
            endShape();
          }
        }
      }
    }
    
    void keyPressed() {
      if (contours==null) {
        println("It is null");
      } else {
        println("Found " + contours.size());
      }
    }
    
    
    void selectImage(final File f) {
      if (f == null || f.isDirectory()) {
    
        println("Window was closed or you've hit cancel.\n");
        System.exit(0);
      }
    
      final String canvasPath = f.getPath();
      println(canvasPath);
      canvas = loadImage(canvasPath); 
      //contours.clear();   //// REMOVE any previous contours as new image loaded!
    
      if (canvas!=null)   
        canvas.resize(width, height);
    } 
    
    public void handleButtonEvents(GButton button, GEvent event) {
    
      if (button == btnFilterO) {
        selectInput("Please select canvas picture:", "selectImage");
      }
    }
    
  • Answer ✓

    Improved by using stages.

    Kf

    import g4p_controls.*;
    import java.awt.Font;
    import gab.opencv.*;
    
    OpenCV opencv;
    
    final int kLoadingStage=0;
    final int kProcessingStage=1;
    final int kReady=2;
    
    ArrayList<Contour> contours;
    ArrayList<Contour> polygons;
    
    PImage canvas;
    float ratio;
    int n = 1;
    
    GButton btnFilterO;
    
    boolean filterO=false;
    int  requestImageStage=kLoadingStage;
    
    
    void setup() {
      size(960, 720);
    
      //surface.setResizable(true);
      btnFilterO = new GButton(this, 180, 20, 140, 20);
      btnFilterO.setText("Open file");
      btnFilterO.setLocalColorScheme(GCScheme.GREEN_SCHEME);
    
      noFill();
      noSmooth();
      strokeWeight(5);
    }
    
    
    void draw() {
      if (canvas == null ) {
        if (requestImageStage!=kLoadingStage) {
          background(0);      
          selectInput("Please select canvas picture:", "selectImage");
        }
      } else {
    
        if (requestImageStage==kProcessingStage) {
    
          opencv = new OpenCV(this, canvas);
          contours = opencv.findContours();
          requestImageStage=kReady;
        } else {
    
          background(canvas);
    
          loadPixels();
          canvas.loadPixels();
    
    
          for (Contour contour : contours) {
    
            stroke(0, 255, 0);
            contour.draw();
            stroke(255, 0, 0);
            beginShape();
            for (PVector point : contour.getPolygonApproximation().getPoints()) {
              vertex(point.x, point.y);
            }
            endShape();
          }
        }
      }
    }
    
    void keyPressed() {
      if (contours==null) {
        println("It is null");
      } else {
        println("Found " + contours.size());
      }
    }
    
    
    void selectImage(final File f) {
      if (f == null || f.isDirectory()) {
    
        println("Window was closed or you've hit cancel.\n");
        System.exit(0);
      }
    
      final String canvasPath = f.getPath();
      println(canvasPath);
      canvas = loadImage(canvasPath); 
      //contours.clear();   //// REMOVE any previous contours as new image loaded!
    
      if (canvas!=null) {
        //canvas.resize(width, height);
        surface.setSize(canvas.width, canvas.height);
        requestImageStage=kProcessingStage;    
      }
    } 
    
    public void handleButtonEvents(GButton button, GEvent event) {
    
      if (button == btnFilterO) {
        requestImageStage=kLoadingStage;
        selectInput("Please select canvas picture:", "selectImage");
      }
    }
    
  • Thanks kfrajer for your great help, everything works well, thanks again!

Sign In or Register to comment.