Convex housing in Java Android Opencv 2.3

Please help me,

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

Before I did it in Java, I did it in C ++ with Visual Studio 2008.

This code can successfully work in C ++.

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

This is my C ++ code:

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 Android code:

 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 information, I made a small modification to Convex Hull in my code. I fill the color inside the outline .

Can anyone help me solve my problem?

I am very grateful for your help.

+4
source share
6 answers

I have no comments to add a comment, just wanted to say that the two answers above helped me get Imgproc.convexHull () to work for my use 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 
+10
source

Looking at the documentation for findContours() and convexHull() , it seems like you have incorrectly specified the contours and hull variables.

Try changing the ads:

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

Then, after calling convexHull() , hull contains the indices of the points in contours that make up the convex hull. To draw points using drawContours() , you will need to populate a new MatOfPoint containing only points on the convex hull, and pass this to drawContours() . I leave this as an exercise for you.

+1
source

To add to what Aurelius said, you used a point vector in your C ++ implementation, so the body matrix contains the actual convex points:

β€œIn the first case, the [integer index vector] hull elements are 0-oriented indices of convex hull points in the original array (since the set of convex hull points is a subset of the original set of points). In the second case, the [point vector] hull elements are convex hull points themselves " - convexHull

That's why you were able to call

 drawContours( drawing, hull, i, Scalar(255, 255, 255), CV_FILLED ); 

In your version of Android, the output of the case is just an array of indices that matches the points in the original matrix of contours.get (i). Therefore, you need to look for convex points in the original matrix. Here is a very rough idea:

 MatOfInt hull = new MatOfInt(); MatOfPoint tempContour = contours.get(i); Imgproc.convexHull(tempContour, hull, false); // O(N*Log(N)) //System.out.println("hull size: " + hull.size() + " x" + hull.get(0,0).length); //System.out.println("Contour matrix size: " + tempContour.size() + " x" + tempContour.get(0,0).length); int index = (int) hull.get(((int) hull.size().height)-1, 0)[0]; Point pt, pt0 = new Point(tempContour.get(index, 0)[0], tempContour.get(index, 0)[1]); for(int j = 0; j < hull.size().height -1 ; j++){ index = (int) hull.get(j, 0)[0]; pt = new Point(tempContour.get(index, 0)[0], tempContour.get(index, 0)[1]); Core.line(frame, pt0, pt, new Scalar(255, 0, 100), 8); pt0 = pt; } 
+1
source

This code works well in my application. In my case, I had several loops for work, so you'll notice a lot of lists, but if you have only one loop, just set it to work without iterations .get (i).

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); } 
+1
source

Java Example (OpenCV 2.4.11)

hullMat contains a gray submask identified by the convexHull method.
You can filter the contours you 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; } 
+1
source

Use fillconvexPoly

  for(;;){ Imgproc.fillConvexPoly(image_2, point,new Scalar(255, 255, 255)); } 
0
source

Source: https://habr.com/ru/post/1490841/


All Articles