首页 > 解决方案 > 排序点[]左右和自上而下

问题描述

我在 Android 中使用 OpenCV 从轮廓应用 4 点变换。我Imgproc.findContours用来寻找轮廓。我找到轮廓的代码:

public MatOfPoint2f FindPaper(Mat edged) {
    List<MatOfPoint> contours = new ArrayList<>();
    Mat hierarchy = new Mat();
    Imgproc.findContours(edged, contours, hierarchy, Imgproc.RETR_EXTERNAL, Imgproc.CHAIN_APPROX_SIMPLE);

    if (contours.size() > 0) {
        Collections.sort(contours, new ContourComparator()); // compare by area

        for (MatOfPoint cnt : contours) {
            MatOfPoint2f matrix = new MatOfPoint2f();
            MatOfPoint2f approxMatrix = new MatOfPoint2f();
            cnt.convertTo(matrix, CvType.CV_32FC2);

            double peri = Imgproc.arcLength(matrix, true);
            Imgproc.approxPolyDP(matrix, approxMatrix, 0.02 * peri, true);
            if (approxMatrix.size().height == 4){
                return approxMatrix;
            }
        }
    }
    return null;
}

下面是我的 4 点变换代码:

public Mat FourPointTransform(Mat input, MatOfPoint2f cutMat){
    Point[] canonicalPoints = new Point[4];
    canonicalPoints[0] = new Point(input.width(), 0);
    canonicalPoints[1] = new Point(0,0);
    canonicalPoints[2] = new Point(0, input.height());
    canonicalPoints[3] = new Point(input.width(), input.height());

    MatOfPoint2f canonicalMarker = new MatOfPoint2f();
    canonicalMarker.fromArray(canonicalPoints);

    // how to sort these points Left-Right to Top-Down?
    //Point[] cutPoints = SortPoint(cutMat.toArray());

    MatOfPoint2f marker = new MatOfPoint2f(cutMat.toArray());
    Mat transform = Imgproc.getPerspectiveTransform(marker, canonicalMarker);
    Mat dest = new Mat(input.rows(), input.cols(), input.type());
    Imgproc.warpPerspective(input, dest, transform, dest.size());

    return dest;
}

有时结果MatFourPointTansform翻转或旋转的。如何对左右和自上而下的点进行排序?

标签: javaandroidopencv

解决方案


经过几天的反复试验,这是我的数组的正确排序。

public static IEnumerable<PointF> SortPoints(IEnumerable<PointF> input)
    {
        var sorted = new PointF[4];
        var listedInput = input.ToList();

        // top-left     --> min(x+y)
        sorted[0] = listedInput.GroupBy(x => x.X + x.Y).OrderBy(x => x.Key).First().First();
        // bottom-right --> max(x+y)
        sorted[2] = listedInput.GroupBy(x => x.X + x.Y).OrderByDescending(x => x.Key).First().First();
        // top-right    --> min(x-y)
        sorted[1] = listedInput.GroupBy(x => x.X - x.Y).OrderBy(x => x.Key).First().First();
        // bottom-left  --> max(x-y)
        sorted[3] = listedInput.GroupBy(x => x.X - x.Y).OrderByDescending(x => x.Key).First().First();

        return sorted;
    }

上面的代码是 C# 并使用 EmguCV。


推荐阅读