首页 文章

OpenCV - 寻找轮廓终点?

提问于
浏览
1

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

3 回答

  • 0

    我正在寻找相同的功能,我看到HoughLinesP有 endpoints ,因为使用的线不是轮廓 . 我正在使用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

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

    以下是找到两个点, 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;
        }
    
  • 0

    基于邻居距离检查的解决方案对我来说不起作用(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))
    

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

相关问题