我在OpenCV 2.3.1中成功实现了轮廓的Delaunay三角剖分。
使用cvPointPolygonTest,我可以获得凸包中的所有三角形,然后我尝试在三角形质心上执行另一个cvPointPolygonTest,以了解它们是否在主轮廓 ,所以我可以拥有约束三角形的轮廓。
但是,它不能很好地运作,因为有些三角形(例如,一个走路的人有两条腿的距离)'越过'一个洞。
有没有人知道执行约束三角测量的方法。我想到了凸性缺陷,但无法理解如何开始这一点。
提前致谢!
本
事实上,它不是一个凸面的船体缺陷问题,而是一个三角形的问题。这张图片会告诉你麻烦:
http://img191.imageshack.us/img191/7527/capturedcran20111128180.png
特别是在三角形船体的底部,您可以看到三角测量位于轮廓中的AND中,因为OpenCV正在对凸包进行三角测量。我想找到一种方法来对轮廓本身进行三角测量。
我发现了一些关于在轮廓中添加Steiner点的想法,但找不到从OpenCV开始的位置。
我的想法是:
我是对的吗?
感谢您的耐心和答案!
答案 0 :(得分:2)
最后,我在我的程序中实现了poly2tri库。
http://img834.imageshack.us/img834/3373/capturedcran20111130143.png
这是结果(OpenCV获取轮廓,然后poly2tri执行三角测量):
// -------------------- poly2tri --------------------
NSMutableArray* temp = [[NSMutableArray alloc] init];
vector<p2t::Triangle*> triangles;
vector< vector<p2t::Point*> > polylines;
vector<p2t::Point*> polyline;
for(int i = 0; i < contour32->total; i++ ) {
CvPoint2D32f* pt32 = CV_GET_SEQ_ELEM(CvPoint2D32f, contour32, i);
polyline.push_back(new p2t::Point((double)pt32->x, (double)pt32->y));
}
polylines.push_back(polyline);
p2t::CDT* cdt = new p2t::CDT(polyline);
// TODO -> holes with CV_RETR_TREE
// Triangulation !
cdt->Triangulate();
// On exporte nos triangles
triangles = cdt->GetTriangles();
for (int i = 0; i < triangles.size(); i++) {
p2t::Triangle& t = *triangles[i];
p2t::Point& a = *t.GetPoint(0);
p2t::Point& b = *t.GetPoint(1);
p2t::Point& c = *t.GetPoint(2);
double x1 = (width / rWidth * (double)a.x) - (width / 2.f);
double y1 = (height / rHeight * (double)a.y) - (height / 2.f);
double x2 = (width / rWidth * (double)b.x) - (width / 2.f);
double y2 = (height / rHeight * (double)b.y) - (height / 2.f);
double x3 = (width / rWidth * (double)c.x) - (width / 2.f);
double y3 = (height / rHeight * (double)c.y) - (height / 2.f);
[temp addObject:[[NSArray arrayWithObjects:
[NSArray arrayWithObjects:
[NSNumber numberWithDouble:x1],
[NSNumber numberWithDouble:y1],
[NSNumber numberWithDouble:0.],
nil],
[NSArray arrayWithObjects:
[NSNumber numberWithDouble:x2],
[NSNumber numberWithDouble:y2],
[NSNumber numberWithDouble:0.],
nil],
[NSArray arrayWithObjects:
[NSNumber numberWithDouble:x3],
[NSNumber numberWithDouble:y3],
[NSNumber numberWithDouble:0.],
nil],
nil] autorelease]];
}
[outDelaunay addObject:temp];
其中contour32是使用cvFindContours找到的OpenCV轮廓,然后转换为float32。
答案 1 :(得分:1)
你必须使用:
CvSeq* cvConvexityDefects(
const CvArr* contour,
const CvArr* convexhull,
CvMemStorage* storage = NULL
);
这将返回CvConvexityDefect
的序列(CvSeq),而不是CvPoint或您可能习惯使用的其他任何CvSeq。
你可以在循环中解决缺陷,如下所示:
CvSeq* defects = cvConvexityDefects(.....);
for (i = 0; i < defects->total; i++)
{
CvConvexityDefect* def = (CvConvexityDefect*)cvGetSeqElem(defects, i);
//do something with them
}
缺陷具有以下结构:
typedef struct CvConvexityDefect {
// point of the contour where the defect begins
CvPoint* start;
// point of the contour where the defect ends
CvPoint* end;
// point within the defect farthest from the convex hull
CvPoint* depth_point;
// distance between the farthest point and the convex hull
float depth;
} CvConvexityDefect;
因此,在获得每个缺陷后,您可以从它们构建一个CvSeq点,并在三角形的质心上使用cvPointPolygonTest
来查看它们是否在它们内部。
如果它们在缺陷内,则意味着它们位于主要轮廓之外。
希望这是你需要的东西,它会有所帮助。