OpenCV - 寻找轮廓终点?

时间:2013-11-01 19:46:11

标签: c++ c opencv contour

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

3 个答案:

答案 0 :(得分:1)

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

struct contoursCmpY {
    bool operator()(const Point &a,const Point &b) const {
        if (a.y == b.y)
            return a.x < b.x;

        return a.y < b.y;
    }
} contoursCmpY_;

vector<Point> 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);

答案 1 :(得分:0)

正如您所说,您始终可以单步执行轮廓点。

以下内容找到了两个点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;
    }

答案 2 :(得分:0)

基于邻居距离检查的解决方案对我来说不起作用(Python + opencv 3.0.0-beta),因为我得到的所有轮廓似乎都折叠在自己身上。什么看起来像&#34;打开&#34;乍一看图像上的轮廓实际上是关闭的&#34;轮廓坍塌了。

所以我不得不求助于&#34; u-turns&#34;在每个轮廓的序列中,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))

不能完全抵御污染尖点并且非常耗时,但这是一个开始。我自然会对其他想法感兴趣:)

相关问题