OpenCV – 寻找轮廓终点?

我正在寻找一种方法来获得从Canny边缘检测中提取的薄轮廓的终点。 我想知道这是可能的一些内置方式。 我计划在轮廓中走动以找到彼此距离最大的两个点(仅沿着轮廓移动),但如果已经存在一种方式则会更容易。 我看到cvarcLength存在以获得轮廓的周长,因此可能有一种内置的方法来实现这一点。 轮廓中的点是否以这样的方式排序,以便可以知道关于端点的一些信息? 还有其他想法吗? 非常感谢!

我正在寻找相同的function,我看到HoughLinesP有端点,因为线条不是轮廓使用的。 我正在使用findContours,所以我发现在下面的轮廓中订购点是有帮助的,而不是将第一个和最后一个点作为起点和终点。

struct contoursCmpY { bool operator()(const Point &a,const Point &b) const { if (ay == by) return ax < bx; return ay < by; } } contoursCmpY_; vector cont; cont.push_back(Point(194,72)); cont.push_back(Point(253,14)); cont.push_back(Point(293,76)); cont.push_back(Point(245,125)); std::sort(cont.begin(),cont.end(), contoursCmpY_); int size = cont.size(); printf("start Point x=%d,y=%d end Point x=%d,y=%d", cont[0].x, cont[0].y, cont[size].x, cont[size].y); 

如你所说,你总是可以逐步完成轮廓点。

下面找到两个点, ptLeftptRight ,沿x的分离最大,但可以根据需要进行修改。

  CvPoint ptLeft = cvPoint(image->width, image->height); CvPoint ptRight = cvPoint(0, 0); CvSlice slice = cvSlice(0, CV_WHOLE_SEQ_END_INDEX); CvSeqReader reader; cvStartReadSeq(contour, &reader, 0); cvSetSeqReaderPos(&reader, slice.start_index); int count = cvSliceLength(slice, contour); for(int i = 0; i < count; i++) { reader.prev_elem = reader.ptr; CV_NEXT_SEQ_ELEM(contour->elem_size, reader); CvPoint* pt = (CvPoint*)reader.ptr; if( pt->x < ptLeft.x ) ptLeft = *pt; if( pt->x > ptRight.x ) ptRight = *pt; } 

基于邻居距离检查的解决方案对我来说不起作用(Python + opencv 3.0.0-beta),因为我得到的所有轮廓似乎都折叠在自己身上。 乍看之下在图像上显示为“开放”轮廓的实际上是“闭合”轮廓在其自身上折叠。

所以我不得不求助于在每个轮廓的序列中寻找“u-turns”,这是Python中的一个例子:

 import numpy as np def draw_closing_lines(img, contours): for cont in contours: v1 = (np.roll(cont, -2, axis=0) - cont) v2 = (np.roll(cont, 2, axis=0) - cont) dotprod = np.sum(v1 * v2, axis=2) norm1 = np.sqrt(np.sum(v1 ** 2, axis=2)) norm2 = np.sqrt(np.sum(v2 ** 2, axis=2)) cosinus = (dotprod / norm1) / norm2 indexes = np.where(0.95 < cosinus)[0] if len(indexes) == 1: # only one u-turn found, mark in yellow cv2.circle(img, tuple(cont[indexes[0], 0]), 3, (0, 255, 255)) elif len(indexes) == 2: # two u-turns found, draw the closing line cv2.line(img, tuple(tuple(cont[indexes[0], 0])), tuple(cont[indexes[1], 0]), (0, 0, 255)) else: # too many u-turns, mark in red for i in indexes: cv2.circle(img, tuple(cont[i, 0]), 3, (0, 0, 255)) 

对污染尖点并不十分强大且非常耗时,但这是一个开始。 我自然会对其他想法感兴趣:)