在android上绘制凸包

时间:2015-03-28 10:35:28

标签: android opencv convex-hull opencv-contour

我尝试在图像上绘制凸包。为此,我找到所有轮廓并选择最大面积轮廓。 drawContours接受MatOfPointconvexHull给我MatOfInt。我读了这个question并运行了一些代码。他们中的一些人绘制了凸包,但他们找不到真正的凸点。

我使用下面的代码,但它在最后一行m.fromArray(hullpoints.get(i));上有运行时错误。 hullpoints.get(i)只有一个点,代码无法创建MatOfPoint个对象。如何从MatOfPoint转换为MatOfInt

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

        // Convert MatOfInt to MatOfPoint for drawing convex hull
        // Loop over all contours
        List<Point[]> hullpoints = new ArrayList<Point[]>();
        for(int j=0; j < hull.size(); j++){
            Point[] points = new Point[hull.get(j).rows()];

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

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

1 个答案:

答案 0 :(得分:1)

Fwiw,我已将FastConvexHullhere更改为使用com.google.android.gms.maps.model.LatLong。经过最低限度的测试,所以没有保证。

接口:

import com.google.android.gms.maps.model.LatLng;
import java.util.ArrayList;

public interface ConvexHullAlgorithm
{
    ArrayList<LatLng> execute(ArrayList<LatLng> points);
}

类别:

public class FastConvexHull implements ConvexHullAlgorithm {

    @Override
    public ArrayList<LatLng> execute(ArrayList<LatLng> points) {
        ArrayList<LatLng> xSorted = (ArrayList<LatLng>) points.clone();
        Collections.sort(xSorted, new XCompare());

        int n = xSorted.size();

        LatLng[] lUpper = new LatLng[n];

        lUpper[0] = xSorted.get(0);
        lUpper[1] = xSorted.get(1);

        int lUpperSize = 2;

        for (int i = 2; i < n; i++) {
            lUpper[lUpperSize] = xSorted.get(i);
            lUpperSize++;

            while (lUpperSize > 2 && !rightTurn(lUpper[lUpperSize - 3], lUpper[lUpperSize - 2], lUpper[lUpperSize - 1])) {
                // Remove the middle point of the three last
                lUpper[lUpperSize - 2] = lUpper[lUpperSize - 1];
                lUpperSize--;
            }
        }

        LatLng[] lLower = new LatLng[n];

        lLower[0] = xSorted.get(n - 1);
        lLower[1] = xSorted.get(n - 2);

        int lLowerSize = 2;

        for (int i = n - 3; i >= 0; i--) {
            lLower[lLowerSize] = xSorted.get(i);
            lLowerSize++;

            while (lLowerSize > 2 && !rightTurn(lLower[lLowerSize - 3], lLower[lLowerSize - 2], lLower[lLowerSize - 1])) {
                // Remove the middle point of the three last
                lLower[lLowerSize - 2] = lLower[lLowerSize - 1];
                lLowerSize--;
            }
        }

        ArrayList<LatLng> result = new ArrayList<LatLng>();

        for (int i = 0; i < lUpperSize; i++) {
            result.add(lUpper[i]);
        }

        for (int i = 1; i < lLowerSize - 1; i++) {
            result.add(lLower[i]);
        }

        return result;
    }

    private boolean rightTurn(LatLng a, LatLng b, LatLng c) {
        return (b.latitude - a.latitude) * (c.longitude - a.longitude) - (b.longitude - a.longitude) * (c.latitude - a.latitude) > 0;
    }

    private class XCompare implements Comparator<LatLng> {
        @Override
        public int compare(LatLng o1, LatLng o2) {
            return (new Float(o1.latitude)).compareTo(new Float(o2.latitude));
        }
    }
}