OpenCV 凸包坐标
OpenCV Convex Hull coordinates
我想找到凸包,以便在纸上绘制手绘三角形的边缘。使用图像处理进行平滑是不够的,因为我也需要检测这个三角形,如果使用 approxPolyDP 函数,手绘三角形往往具有三个以上的点。 approxPolyDP 函数正确识别了三角形的凸包。
问题是,我在图像中还有其他形状,在这些形状上创建了凸包。
Before convex hull is used: Notice the contour labelled 3
After convex hull is used: the end points have been joined and the contour labelled 3 forms a triangle
现在我想以某种方式排除轮廓 3 被检测为三角形。
为此,我的策略是从名为 hullMop 的 ArrayList 中完全删除此轮廓。这是因为我的三角形检测函数使用了 hullMop 的轮廓,所以它甚至不会检查标记为 3 的轮廓。
extcontours是使用凸包之前的轮廓。
此函数检查来自 hullMop 的点是否在 extcontours 内。如果不是,则必须从 hullMop 中删除,因为它们是由于凸包而生成的额外点集,或者换句话说,第二张图像中的红线。
现在我觉得我的概念有漏洞。 openCV 文档说凸包 returns 是原始数组点的子集,换句话说,是 extcontours 点的子集。
我的问题是,如何获取由 convexHull 函数创建的红线的点。我不想使用 findContours 因为我觉得有更好的方法。
private void RemoveFalseHullTriangles(ArrayList<MatOfPoint> extcontours, ArrayList<MatOfPoint> hullMop, int width, int height) {
//if every single point of hullmop doesnt touch or isn't inside extcontours, then that point must be the red line
MatOfPoint2f Contours2f = new MatOfPoint2f();
double [] newA = new double[2];
int hullCounter = 0;
A: for(int i =0;i<extcontours.size();i++) {
MatOfPoint ExtCnt = extcontours.get(i);
MatOfPoint HullCnt = hullMop.get(hullCounter);
ExtCnt.convertTo(Contours2f, CvType.CV_32F);
B: for (int j = 0; j < HullCnt.rows(); j++) {
double[] pt = new double[2];
pt[0] = HullCnt.get(j,0)[0];
pt[1] = HullCnt.get(j,0)[1];
if (Math.abs(Imgproc.pointPolygonTest(Contours2f, new Point(pt), true)) > 40) {
//Remove index from HullMop
hullMop.remove(hullCounter);
hullCounter--;
break B;
}
}
hullCounter++;
}
}
因为hullMop只有extcontours点的一个子集,所以我可能永远不知道使用凸包后标记为3的轮廓红线的点。
除了使用 findContours 之外,还有什么方法可以获取由凸包生成的那条红线的坐标吗?
正如 Alexandar Reynolds 所提到的,问题实际上是首先检测开放轮廓并在找到凸包之前排除这些轮廓。
这里解释了寻找开放轮廓的方法:
Recognize open and closed shapes opencv
基本上,如果外部轮廓在层次结构中没有子轮廓,那么它就是一个开放轮廓,必须在找到凸包之前排除(对于我的情况)。
我想找到凸包,以便在纸上绘制手绘三角形的边缘。使用图像处理进行平滑是不够的,因为我也需要检测这个三角形,如果使用 approxPolyDP 函数,手绘三角形往往具有三个以上的点。 approxPolyDP 函数正确识别了三角形的凸包。
问题是,我在图像中还有其他形状,在这些形状上创建了凸包。
Before convex hull is used: Notice the contour labelled 3
After convex hull is used: the end points have been joined and the contour labelled 3 forms a triangle
现在我想以某种方式排除轮廓 3 被检测为三角形。 为此,我的策略是从名为 hullMop 的 ArrayList 中完全删除此轮廓。这是因为我的三角形检测函数使用了 hullMop 的轮廓,所以它甚至不会检查标记为 3 的轮廓。
extcontours是使用凸包之前的轮廓。 此函数检查来自 hullMop 的点是否在 extcontours 内。如果不是,则必须从 hullMop 中删除,因为它们是由于凸包而生成的额外点集,或者换句话说,第二张图像中的红线。
现在我觉得我的概念有漏洞。 openCV 文档说凸包 returns 是原始数组点的子集,换句话说,是 extcontours 点的子集。
我的问题是,如何获取由 convexHull 函数创建的红线的点。我不想使用 findContours 因为我觉得有更好的方法。
private void RemoveFalseHullTriangles(ArrayList<MatOfPoint> extcontours, ArrayList<MatOfPoint> hullMop, int width, int height) {
//if every single point of hullmop doesnt touch or isn't inside extcontours, then that point must be the red line
MatOfPoint2f Contours2f = new MatOfPoint2f();
double [] newA = new double[2];
int hullCounter = 0;
A: for(int i =0;i<extcontours.size();i++) {
MatOfPoint ExtCnt = extcontours.get(i);
MatOfPoint HullCnt = hullMop.get(hullCounter);
ExtCnt.convertTo(Contours2f, CvType.CV_32F);
B: for (int j = 0; j < HullCnt.rows(); j++) {
double[] pt = new double[2];
pt[0] = HullCnt.get(j,0)[0];
pt[1] = HullCnt.get(j,0)[1];
if (Math.abs(Imgproc.pointPolygonTest(Contours2f, new Point(pt), true)) > 40) {
//Remove index from HullMop
hullMop.remove(hullCounter);
hullCounter--;
break B;
}
}
hullCounter++;
}
}
因为hullMop只有extcontours点的一个子集,所以我可能永远不知道使用凸包后标记为3的轮廓红线的点。 除了使用 findContours 之外,还有什么方法可以获取由凸包生成的那条红线的坐标吗?
正如 Alexandar Reynolds 所提到的,问题实际上是首先检测开放轮廓并在找到凸包之前排除这些轮廓。 这里解释了寻找开放轮廓的方法: Recognize open and closed shapes opencv
基本上,如果外部轮廓在层次结构中没有子轮廓,那么它就是一个开放轮廓,必须在找到凸包之前排除(对于我的情况)。