OpenCV - 闭合轮廓 (Java)
OpenCV - Closing contours (Java)
我目前正在尝试关闭这张图片右侧的轮廓:
Sample。
打开轮廓的原因在于kabeja
,一个将DXF文件转换为图像的库。似乎在某些图像上它不会转换最后一个像素列(或行),这就是示例图片打开的原因。
我有想法在Opencv中使用Core.copyMakeBorder()
,给图片添加一些space。之后我尝试使用 Imgproc.approxPolyDP()
来关闭轮廓,但这不起作用。我用不同的 Epsilon 值尝试了这个:图片编辑:不能 post 超过 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;
}
此致,
布克
假设假设是正确的,最后一行(对于列来说是相似的)没有转换(即丢失),然后尝试以下操作。假设 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;
}
}
我目前正在尝试关闭这张图片右侧的轮廓:
Sample。
打开轮廓的原因在于kabeja
,一个将DXF文件转换为图像的库。似乎在某些图像上它不会转换最后一个像素列(或行),这就是示例图片打开的原因。
我有想法在Opencv中使用Core.copyMakeBorder()
,给图片添加一些space。之后我尝试使用 Imgproc.approxPolyDP()
来关闭轮廓,但这不起作用。我用不同的 Epsilon 值尝试了这个:图片编辑:不能 post 超过 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;
}
此致, 布克
假设假设是正确的,最后一行(对于列来说是相似的)没有转换(即丢失),然后尝试以下操作。假设 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;
}
}