Machine Vision - Detecting circles (OpenCV)

So i am trying to detect some test tubes with a webcam, so i can pick them up using a robot. I have successfully detected the straight lines and from there i can get the position and orientation of the line. For this task i am using OpenCV library for Processing and then using the linedetection (see picture)

What i need now is to figure out what is up and down on the tube. Hence i would like to detect the half circle which correspond to the bottom of the tube. The problem here being that HoughCircles are not a part of the OpenCV library for processing. It is however a part of the OpenCV library for java (or Python).

https://opencv.org/

Are there anyway to install the full Java OpenCV package for Processing? I could not get it to work, since there was no jar. extension in the OpenCV (for Java) download.

Any other way of detecting a half circle in Processing are welcome as well.

1 Like

I have two suggestions that are related but not sure if it will provide you a desirable solution. I suggest you explore the provided examples that comes with the libraries:

Tutorial Processing - BoofCV

BlobDetection

Kf

Thank you for the quick reply.

Blobdetection will only draw an outer line around a cluster of pixels with the same colour, which is basically what i already have when i draw the outer perimeter.

BoofCV have an elipse function, but it seems that what it does is fit an elipse around a blob… and in this case the blob will be the whole test tube (or maybe more if they lay close to eachother, as some of them are in the attached picture).

What i need is to search out circles in the picture and then sort them by a min and maximum diameter.

Or other suggestions?

Ok, I was sort of writing a long post of one approach using this: http://boofcv.org/index.php?title=Example_Detect_Lines

However, I discard it and I think it is better if you use the example from blobScanner (not sure if this comes with the blobDetection library or is another separate lib). You should run the example that comes with this library. In the PDE, go to File>>Examples and then Contributed libraries>>Blobscanner>>blobcontour>>drawBlobContour, this last is a pde file. If this example works for you, it will make your life sort of simple. My understanding is that you apply a filter to make your image bichromatic and then the algorithm will return a set of points that border each test tube. The challenge here is that each test tube needs to be identified as a single unit which might not work in your case unless you create an algorithm that fixes this issue.

If you are able to get the contour of each test tube, then you can draw that contour in a separate canvas and apply line detection algorithms to a single tube. If you use a line detection algorithm, I will bet you will get three lines and the end with no line would be the curve side.

This would be my approach.

Kf

I did think along those lines (get it? :stuck_out_tongue: ), but as i see it there are two problems with this approach:

  1. The open end of the the tube is not necessarily a straight line because of the lens distortion (if you see the picture you can see that it is slightly curved. Could be a problem, but perhaps not.

  2. The separation issue that you mentioned, is not easy to solve. There could easily be two tubes that lie close together, with the open ends pressed together, effectively hiding the line. However it is not geometrically possible for two tubes to hide the curved bottomline, since two tubes will only be touching on a very small part of the curve. This is why i am so keen on the circle detection, because it solves the two above mentioned problems very easily.

@Palmhoej – on the Processing OpenCV library repo there is an open issue on Hough Circles, and someone mentions a partial workaround:

I was thrilled it looked exactly what i needed. I tried the different examples, but it all came down to that the:

ArrayList circles;

Did not exist, probably because it is not implemented in the Processing branch of opencv.

Same history with the findCircle command :frowning:

The partial workaround, as far as i could tell (was just 4 lines of general idea coding) looked like it was just a bloop detection followed up with a bounding box and the draw a circle inside this box. So basically it did not look for circles, but if your image consisted of only circles, it would be able to draw a circle around these… unfortunatly my pictures does contain other thing than circles.

But thanks for the answer :slight_smile: Maybe i will have to move over to Java to be able to use the full OpenCV. Its just a shame, because i feel that i came very close with my code in Processing. I only needed the circle detector.

That doesn’t sound right…?

ArrayList is built in to Processing.

If you are using a library that does not include it and needs it, you can also import it from Java at the top of your Processing sketch .java class file with import java.util.ArrayLIst

https://docs.oracle.com/javase/7/docs/api/java/util/ArrayList.html

Okay so here are the code i tried to run… it complains about the Arraylist in my processing. If you find a workaround i would be thrilled, since this code is exactly what i am looking for :slight_smile:

import gab.opencv.*;
import org.opencv.imgproc.Imgproc;
import org.opencv.core.Mat;

OpenCV opencv;
PImage src;

ArrayList<Circle> circles;

void setup(){
  src = loadImage("cans.jpg");
  src.resize(800,0);
  opencv = new OpenCV(this, src);
 
   
   size(opencv.width, opencv.height);

  circles = new ArrayList<Circle>();   
}

void draw(){
  opencv.loadImage(src);
//  opencv.setROI(mouseX, mouseY, 90, 100);
//  opencv.threshold(190);
  
  image(opencv.getOutput(),0,0);
  noFill();
  stroke(0,255,0);
  strokeWeight(3);
  for(Circle circle : circles){
    circle.draw();
  }
}

void keyPressed(){
  findCircles();
}

void findCircles(){
  Mat cs = new Mat();
  println("find hough circles");
  Imgproc.HoughCircles(opencv.getGray(), cs, Imgproc.CV_HOUGH_GRADIENT, opencv.getGray().rows()/20, 50);
  
  println();
  
  for(int i = 0; i < cs.cols(); i++){
    println(i);
    circles.add(new Circle((float)cs.get(0,i)[0], (float)cs.get(0,i)[1], (float)cs.get(0,i)[2]));
  }

  
  println(cs.cols() + "x" + cs.rows());
  
}

could you copy paste you specific error message?

Cannot find a class or typed named “Circle”

That makes sense. There is no object / class named “Circle” built-in to Processing – so it doesn’t know what an ArrayList is. As far as I know there is also no Circle built-in to opencv…?

https://docs.opencv.org/java/2.4.3.1/overview-tree.html

Perhaps your original source for that line of code also included a .java file Circle.java, that contains a class definition…?

class Circle {
  // Circle is defined here
}

Hi there, I too am interested in your results. I am writing an app to determine when the person Blinks, and then do something while they are blinking, I am using open CV in processing and it sort of works , but slow. I think if I can apply, Hough Circle Transform, I would be able to focus on the pupil, and everything will run much faster. How were you able to use this inside the processing IDE? Did you find out the line that you need to put on the top to import it from Java? the OpenCV library for processing does not include this… at least I have not been able to find it…

Many thanks