2013-07-11 106 views
4

请帮我,在Java Android Opencv 2.3凸壳Hull

我有一个问题,在凸面赫尔在Android上。我使用Java和OpenCV 2.3

之前我做了Java的,我与Visual Studio 2008

该代码可工作于C运行成功++使它在C++。

现在,我想在Android上将它从C++转换为Java。当我在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模拟器上运行它时,窗口出现错误,“应用程序意外停止”,并被告知通过单击“强制关闭”来停止。当我检查日志猫错误的Eclipse,我发现该进程停止在这一行“Imgproc.convexHull(contours.get(i),hull.get(i),false);” 我不知道为什么这个过程停在那条线上。 你不能帮我解释一下吗? – Jenang

+0

我想我在声明“hull”变量时犯了一个错误。 但是,我不知道如何解决这个问题。我想我已经按照适用的规定宣布了这个变量。 您的意见如何? 您是否认为我的代码中的变量“hull”声明不正确? – Jenang

回答

1

查看findContours()convexHull()的文档,看起来您已经错误地声明了变量contourshull

尝试改变了声明:

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

在你的Android版本,船体输出仅仅是其对应点在原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; 
}