2013-07-11 2 views
4

Пожалуйста, помогите мне,Convex Hull на Java Android Opencv 2.3

У меня проблема с выпуклым корпусом на Android. Я использую Java и OpenCV 2.3.

Прежде, чем я сделал это на Java, я сделал это на C++ с Visual Studio 2008.

Этот код может успешно работает на C++.

Теперь я хочу преобразовать его из C++ в Java на Android. И я нашел ошибку, например, «force close», когда я запускаю ее на SDK Android-симуляторе.

Это мой код на 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 
} 

И это мой код на 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); 
    } 

Для вашей информации, я сделал небольшую модификацию на оконтуривающем в моем коде. Я заполняю цвет внутри контура.

Любой может помочь мне решить мою проблему?

Я очень благодарен вам за помощь.

+0

Трудно сказать, что является причиной вашей проблемы. Какова конкретная ошибка, которую вы получаете? Есть ли связанные с ним записи журнала? – Aurelius

+0

Когда я запустил его на SDK Android Simulator, появилась ошибка Windows, «приложение неожиданно остановилось», и мне сказали остановиться, нажав «Force Close». И когда я проверил ошибку Log Cat Eclipse, я обнаружил, что процесс останавливается в этой строке «Imgproc.convexHull (contours.get (i), hull.get (i), false); Я не знаю, почему процесс остановился на этой линии. Разве вы не можете мне объяснить? – Jenang

+0

Я думаю, что допустил ошибку при объявлении переменной «корпус». Но, я не знаю, как решить эту проблему. Я думаю, что я указал эту переменную в соответствии с применимыми положениями. Как насчет вашего мнения? Считаете ли вы, что объявление переменной «корпус» в моем коде неверно? – Jenang

ответ

1

Если вы указали на документацию findContours() и convexHull(), выяснилось, что вы указали переменные contours и hull неправильно.

Попробуйте изменить объявления для:

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

Затем, после того, как вы называете convexHull(), hull содержит индексам точек в contours, которые содержат выпуклую оболочку. Чтобы нарисовать точки с drawContours(), вам нужно будет заполнить новый MatOfPoint, содержащий только точки на выпуклой оболочке, и передать это drawContours(). Я оставляю это как упражнение для вас.

1

Чтобы добавить к тому, что сказал Аврелий, в вашем C++ реализации вы использовали вектор точек, поэтому матрица оболочки содержит фактические выпуклые точки:

«В первом случае [целочисленный вектор индексов] , элементы корпуса являются 0-ориентированными индексами выпуклых точек корпуса в исходном массиве (так как множество выпуклых точек корпуса является подмножеством исходного точечного множества). Во втором случае [вектор точек] элементы корпуса являются выпуклые оболочки ». - convexHull

Вот почему вы были в состоянии назвать

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

В андроид версии, выходной корпус просто массив индексов, которые соответствуют точкам в исходном contours.get (я) Матрица. Поэтому вам нужно искать выпуклые точки в исходной матрице.Вот очень грубая мысль:

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; 
} 
10

Не имеет репутацию добавить комментарий, просто хотел сказать два ответа выше помогли мне получить Imgproc.convexHull() работает для моего случая использования с чем-то вроде этого (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 
1

Этот код хорошо работает в моем приложении. В моем случае у меня было несколько контуров для работы, поэтому вы заметите много списков, но если у вас есть только один контур, просто настройте его на работу без итераций .get (i).

В этой статье объясняется процесс более просто.

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

Пример на Java (OpenCV 2.4.11)

hullMat содержит вспомогательный мат из gray, как это определено с помощью метода convexHull.
Возможно, вы захотите отфильтровать контуры, которые вам действительно нужны, например, на основе их площади.

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; 
}