Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convex Hull on Java Android Opencv 2.3

Please help me,

I have a problem for Convex Hull on Android. I use Java and OpenCV 2.3.

Before I made it on Java, I made it on C++ with Visual Studio 2008.

This code can running successfully on C++.

Now, i want to convert it from C++ to Java on Android. And I found error like "force close" when i run it on SDK Android simulator.

This is my code on C++:

vector<vector<Point> > contours;
vector<Vec4i> hierarchy;

findContours( canny_output, contours, hierarchy, CV_RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(0, 0) );
drawing = Mat::zeros( canny_output.size(), CV_64F );

/// Find the convex hull object for each contour
vector<vector<Point> > hull ( contours.size() );
for( int i = 0; i < contours.size(); i++ )
  {  convexHull( Mat(contours[i]), hull[i], false );
}

for(size_t i = 0; i < contours.size(); i++){
    drawContours( drawing, hull, i, Scalar(255, 255, 255), CV_FILLED ); // FILL WHITE COLOR
}

And this is my code on Android:

Mat hierarchy = new Mat(img_canny.rows(),img_canny.cols(),CvType.CV_8UC1,new Scalar(0));
    List<Mat> contours =new ArrayList<Mat>();
    List<Mat> hull = new ArrayList<Mat>(contours.size());
    drawing = Mat.zeros(img_canny.size(), im_gray);

    Imgproc.findContours(img_dilasi, contours, hierarchy,Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE, new Point(0, 0));

    for(int i=0; i<contours.size(); i++){
        Imgproc.convexHull(contours.get(i), hull.get(i), false);

    }
    for(int i=0; i<contours.size(); i++){
        Imgproc.drawContours(drawing, hull, i, new Scalar(255.0, 255.0, 255.0), 5);
    }

For your info, I did a little modification on Convex Hull at my code. I fill a color inside contour.

Anyone can help me to solve my problem?

I'm very grateful for your help.

like image 639
Jenang Avatar asked Jul 11 '13 06:07

Jenang


3 Answers

Don't have the rep to add comment, just wanted to say the two answers above helped me get Imgproc.convexHull() working for my use case with something like this (2.4.8):

MatOfPoint mopIn = ...
MatOfInt hull = new MatOfInt();
Imgproc.convexHull(mopIn, hull, false);

MatOfPoint mopOut = new MatOfPoint();
mopOut.create((int)hull.size().height,1,CvType.CV_32SC2);

for(int i = 0; i < hull.size().height ; i++)
{
    int index = (int)hull.get(i, 0)[0];
    double[] point = new double[] {
        mopIn.get(index, 0)[0], mopIn.get(index, 0)[1]
    };
    mopOut.put(i, 0, point);
}           
// do something interesting with mopOut
like image 116
medloh Avatar answered Sep 24 '22 22:09

medloh


This code works well in my application. In my case, I had multiple contours to work with, so you will notice a lot of Lists, but if you only have one contour, just adjust it to work without the .get(i) iterations.

This thread explains the process more simply.

android java opencv 2.4 convexhull convexdefect

   // Find the convex hull
            List<MatOfInt> hull = new ArrayList<MatOfInt>();
            for(int i=0; i < contours.size(); i++){
                hull.add(new MatOfInt());
            }
            for(int i=0; i < contours.size(); i++){
                Imgproc.convexHull(contours.get(i), hull.get(i));
            }

            // Convert MatOfInt to MatOfPoint for drawing convex hull

            // Loop over all contours
            List<Point[]> hullpoints = new ArrayList<Point[]>();
            for(int i=0; i < hull.size(); i++){
                Point[] points = new Point[hull.get(i).rows()];

                // Loop over all points that need to be hulled in current contour
                for(int j=0; j < hull.get(i).rows(); j++){
                    int index = (int)hull.get(i).get(j, 0)[0];
                    points[j] = new Point(contours.get(i).get(index, 0)[0], contours.get(i).get(index, 0)[1]);
                }

                hullpoints.add(points);
            }

            // Convert Point arrays into MatOfPoint
            List<MatOfPoint> hullmop = new ArrayList<MatOfPoint>();
            for(int i=0; i < hullpoints.size(); i++){
                MatOfPoint mop = new MatOfPoint();
                mop.fromArray(hullpoints.get(i));
                hullmop.add(mop);
            }


            // Draw contours + hull results
            Mat overlay = new Mat(binaryImage.size(), CvType.CV_8UC3);
            Scalar color = new Scalar(0, 255, 0);   // Green
            for(int i=0; i < contours.size(); i++){
                Imgproc.drawContours(overlay, contours, i, color);
                Imgproc.drawContours(overlay, hullmop, i, color);
            }
like image 35
user4473007 Avatar answered Sep 24 '22 22:09

user4473007


Example in Java (OpenCV 2.4.11)

hullMat contains the sub mat of gray, as identified by the convexHull method.
You may want to filter the contours you really need, for example based on their area.

List<MatOfPoint> contours = new ArrayList<MatOfPoint>();
MatOfInt4 hierarchy = new MatOfInt4();
MatOfInt hull = new MatOfInt();

void foo(Mat gray) {
    Imgproc.findContours(gray, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);        
    for (int i = 0; i < contours.size(); i++) {
        Imgproc.convexHull(contours.get(i), hull);
        MatOfPoint hullContour = hull2Points(hull, contours.get(i));
        Rect box = Imgproc.boundingRect(hullContour);
        Mat hullMat = new Mat(gray, box);
        ...
    }
}

MatOfPoint hull2Points(MatOfInt hull, MatOfPoint contour) {
    List<Integer> indexes = hull.toList();
    List<Point> points = new ArrayList<>();
    MatOfPoint point= new MatOfPoint();
    for(Integer index:indexes) {
        points.add(contour.toList().get(index));
    }
    point.fromList(points);
    return point;
}
like image 35
Hey StackExchange Avatar answered Sep 26 '22 22:09

Hey StackExchange