OpenCV - 关闭轮廓(Java)

时间:2017-01-17 10:29:00

标签: java opencv image-processing opencv-contour

我目前正试图关闭此图片右侧的轮廓: Sample。 打开轮廓的原因在于kabeja,这是一个将DXF文件转换为图像的库。似乎在某些图像上它不会转换最后一个像素列(或行)以及样本图片打开的原因。

我有想在Opencv中使用Core.copyMakeBorder(),为图片添加一些空间。之后,我尝试使用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 个答案:

答案 0 :(得分:0)

假设假设是正确的,那么最后一行(对于相似的列)不转换(即丢失),则尝试以下操作。假设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; 
    }
}