Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get x,y coordinates of extracted objects in javacv?

Currently I am developing image processing project and I'm using javacv to develop image processing components. I was able to extract some interesting parts of a image and now I need to read the x and y coordinates of those objects. This is the image that I haveextracted

enter image description here

And I need to identify those objects and draw square around those objects. I went through some tutorials and try to identify objects using following code.

    IplImage img="sourceimage";
    CvSize sz = cvSize(img.width(), img.height());
    IplImage gry=cvCreateImage(sz, img.depth(), 1);
    cvCvtColor(img, gry, CV_BGR2GRAY);
    cvThreshold(gry, gry, 200, 250, CV_THRESH_BINARY);


    CvMemStorage mem = CvMemStorage.create();
    CvSeq contours = new CvSeq();
    CvSeq ptr = new CvSeq();
    cvFindContours(gry, mem, contours, Loader.sizeof(CvContour.class) , CV_RETR_CCOMP, CV_CHAIN_APPROX_SIMPLE, cvPoint(0,0));

    CvRect boundbox;

    for (ptr = contours; ptr != null; ptr = ptr.h_next()) {
        boundbox = cvBoundingRect(ptr, 0);
        if(boundbox.height()>10||boundbox.height()>10){
            cvRectangle( gry, cvPoint( boundbox.x(), boundbox.y() ), cvPoint( boundbox.x() + boundbox.width(), boundbox.y() + boundbox.height()),CvScalar.BLUE, 0, 0, 0 );
            System.out.println(boundbox.x()+", "+boundbox.y());
        }
    }
    cvShowImage("contures", gry);
    cvWaitKey(0);

But it doesn't draw as rectangle around the objects. I would like to know whether I can use cvFindContours method to identify those objects ? Please can some one explain how to archive my objective using javacv/opencv?

like image 615
Gum Slashy Avatar asked Aug 24 '12 09:08

Gum Slashy


4 Answers

Try to go through following code and it will give answer for your question.

    IplImage img=cvLoadImage("pathtosourceimage");
    CvSize cvSize = cvSize(img.width(), img.height());
    IplImage gry=cvCreateImage(cvSize, img.depth(), 1);
    cvCvtColor(img, gry, CV_BGR2GRAY);
    cvThreshold(gry, gry, 200, 255, CV_THRESH_BINARY);
    cvAdaptiveThreshold(gry, gry, 255, CV_ADAPTIVE_THRESH_MEAN_C, CV_THRESH_BINARY_INV, 11, 5);

    CvMemStorage storage = CvMemStorage.create();
    CvSeq contours = new CvContour(null);

    int noOfContors = cvFindContours(gry, storage, contours, Loader.sizeof(CvContour.class), CV_RETR_CCOMP, CV_CHAIN_APPROX_NONE, new CvPoint(0,0));

    CvSeq ptr = new CvSeq();

    int count =1;
    CvPoint p1 = new CvPoint(0,0),p2 = new CvPoint(0,0);

    for (ptr = contours; ptr != null; ptr = ptr.h_next()) {

        CvScalar color = CvScalar.BLUE;
        CvRect sq = cvBoundingRect(ptr, 0);

            System.out.println("Contour No ="+count);
            System.out.println("X ="+ sq.x()+" Y="+ sq.y());
            System.out.println("Height ="+sq.height()+" Width ="+sq.width());
            System.out.println("");

            p1.x(sq.x());
            p2.x(sq.x()+sq.width());
            p1.y(sq.y());
            p2.y(sq.y()+sq.height());
            cvRectangle(img, p1,p2, CV_RGB(255, 0, 0), 2, 8, 0);
            cvDrawContours(img, ptr, color, CV_RGB(0,0,0), -1, CV_FILLED, 8, cvPoint(0,0));
            count++;

    }

    cvShowImage("contures",img);
    cvWaitKey(0);

This is the output that I got for your given image.

enter image description here

like image 198
SL_User Avatar answered Nov 05 '22 04:11

SL_User


Did you know that findContours function finds white contours on black background?

Just do bitwise_not (or analogue in JavaCV) to your image and after this apply findContours. This is actually fix to your problem.

like image 20
ArtemStorozhuk Avatar answered Nov 05 '22 02:11

ArtemStorozhuk


No need for third party libraries! What you are looking for can be achieved in OpenCV using a technique known as bounding box:

enter image description here

The trick is to use cvFindContours() to retrieve the contours and then cvApproxPoly() to improve the result. Notice that you'll have to invert the colors of the input image using cvNot() because cvFindContours() search for white contours.

  • There's a nice introduction to contours in this post.
  • There's a Java demo that implements a version of the bounding box to detect car number plates.

By the way cvMinEnclosingCircle() returns the center of the circle as CvPoint2D32f.

like image 4
karlphillip Avatar answered Nov 05 '22 03:11

karlphillip


cvFindContours is the right solution to your problem.
And I have verified that it works on your images.
Here is my experiment

You have System.out.println inside, what's the output?

cvFindContours could be tricky to use, I have wrapped it into a more general C++ function. Also I use a class called vBlob to describe an object cvFindContours detects. From what I see from your java code, java version API is very similar to C/C++ version. So it won't be hard to rewrite it.

ps. Astor gave the right answer.

like image 4
vinjn Avatar answered Nov 05 '22 03:11

vinjn