OpenCV-замкнутые контуры (Java)

В настоящее время я пытаюсь закрыть контуры справа от этой картины:
Образец .
Причина открытия контура заключается в kabejaбиблиотеке для преобразования файлов DXF в изображения. Кажется, что на некоторых изображениях он не преобразует последний столбец пикселя (или строку), и поэтому образец изображения открыт.

У меня была идея использовать Core.copyMakeBorder()Opencv, чтобы добавить немного пространства к картине. После этого я попытался использоватьImgproc.approxPolyDP(), чтобы закрыть контур, но это не работает. Я пробовал это с различными значениями Epsilon: pics EDIT: не могу опубликовать более 2 ссылок

Причина этого, возможно, в том, что контур окружает линию. Он никогда не закрывает контур там, где я хочу.

Я попробовал использовать другой методImgproc.convexHull(), который обеспечивает этот: ConvexHull .
Это может быть полезно для меня, но я понятия не имею, как взять часть выпуклой оболочки, в которой я нуждаюсь, и объединить ее вместе с контуром, чтобы закрыть ее.

Я надеюсь, что у кого-то есть идея.

Вот мой метод для Imgproc.approxPolyDP()

public static ArrayList<MatOfPoint> makeComplete(Mat mat) {
    System.out.println("makeComplete: START");
    Mat dst = new Mat();
    Core.copyMakeBorder(mat, dst, 10, 10, 10, 10, Core.BORDER_CONSTANT);

    ArrayList<MatOfPoint> cnts = Tools.getContours(dst);
    ArrayList<MatOfPoint2f> opened = new ArrayList<>();

    //convert to MatOfPoint2f to use approxPolyDP
    for (MatOfPoint m : cnts) {
        MatOfPoint2f temp = new MatOfPoint2f(m.toArray());
        opened.add(temp);
        System.out.println("First loop runs");
    }

    ArrayList<MatOfPoint> closed = new ArrayList<>();
    for (MatOfPoint2f conts : opened) {
        MatOfPoint2f temp = new MatOfPoint2f();
        Imgproc.approxPolyDP(conts, temp, 3, true);
        MatOfPoint closedTemp = new MatOfPoint(temp.toArray());
        closed.add(closedTemp);
        System.out.println("Second loop runs");
    }

    System.out.println("makeComplete: END");
    return closed;
}

И вот код для Imgproc.convexHull()

 public static ArrayList<MatOfPoint> getConvexHull(Mat mat) {
    Mat dst = new Mat();
    Core.copyMakeBorder(mat, dst, 10, 10, 10, 10, Core.BORDER_CONSTANT);

    ArrayList<MatOfPoint> cnts = Tools.getContours(dst);
    ArrayList<MatOfPoint> out = new ArrayList<MatOfPoint>();
    MatOfPoint mopIn = cnts.get(0);
    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);
    }

    out.add(mopOut);
    return out;
}

С уважением,
Brk

1 ответ

  1. Предположив, что предположение верно, что последняя строка (для столбца она похожа) не преобразуется (т. е. отсутствует), попробуйте следующее. Предположим, что x идет слева направо, а y сверху вниз. Добавим одну строку пустого (белого?) пиксели в нижней части изображения, а затем перейти слева направо. Ниже приведен псевдо-код:

    // EMPTY - value of backgroung e.g. white for the sample image
    PixelType curPixel = EMPTY;
    int y = height - 1; // last row, the one we added
    for (int x = 0; x < width; ++x)
    {
        // img(y,x) - current pixel, is "empty"
        // img (y-1, x) - pixel above the current
        if (img(y-1, x) != img(y, x))
        {
            // pixel above isn't empty, so we make current pixel non-empty
            img(y, x) = img(y-1, x);
            // if we were drawing, then stop, otherwise - start
            if (curPixel == EMPTY)
                curPixel = img(y-1, x);
            else
                curPixel = EMPTY;
        }
        else
        {
            img(y, x) = curPixel; 
        }
    }