OpenCV检测轮廓交叉点

时间:2011-12-18 14:28:58

标签: c++ opencv

我有2个轮廓A和B,我想检查它们是否相交。 A和B都是cv :: Point类型的向量,并且具有不同大小

要检查交叉点,我试图执行 bitwise_and 。这是一个例外,因为输入的大小不同。我该如何解决 ?

编辑:

附图应该可以更好地了解这个问题。汽车由蓝色轮廓跟踪,障碍物由粉红色轮廓跟踪。我需要检查交叉点。 enter image description here

4 个答案:

答案 0 :(得分:11)

一种简单但可能不是最有效(??)的方法是使用drawContours创建两个图像:一个具有汽车轮廓,另一个具有障碍轮廓。

然后and他们在一起,任何仍然是积极的点将是交叉点。

一些伪代码(我使用Python接口,所以不能正确使用C ++语法,但它应该足够简单,你可以转换):

import numpy as np # just for matrix manipulation, C/C++ use cv::Mat
# find contours.
contours,h = findContours( img, mode=RETR_LIST, method=CHAIN_APPROX_SIMPLE )
# Suppose this has the contours of just the car and the obstacle.

# create an image filled with zeros, single-channel, same size as img.
blank = np.zeros( img.shape[0:2] )

# copy each of the contours (assuming there's just two) to its own image. 
# Just fill with a '1'.
img1 = drawContours( blank.copy(), contours, 0, 1 )
img2 = drawContours( blank.copy(), contours, 1, 1 )

# now AND the two together
intersection = np.logical_and( img1, img2 )

# OR we could just add img1 to img2 and pick all points that sum to 2 (1+1=2):
intersection2 = (img1+img2)==2

如果我看intersection,我会得到一张图像,其中轮廓相交,其他地方为0。

或者,您可以使用drawContours( blank.copy(), contours, 0, 1, thickness=-1 )填写整个轮廓(不仅仅是轮廓,还可以填充内部),然后intersection图像将包含轮廓之间的交叉。

答案 1 :(得分:0)

如果您首先对矢量进行排序,使用几乎任何一致的排序标准,那么您可以直接在矢量上使用std::set_intersection。如果轮廓与图像尺寸相比较短,则这可能比接受的答案更快。

答案 2 :(得分:0)

我发现Clipper库对于这些目的非常有用。 (将cv::Point的向量转换为Clipper Path对象非常简单。)

答案 3 :(得分:0)

C ++经过测试的代码,基于math.coffee的答案:

    vector< Point> merge_contours(vector <Point>& contour1, vector <Point>& contour2, int type){
    // get work area        
    Rect work_area = boundingRect( contour1 ) | boundingRect( contour2 );        
    
    Mat merged = Mat::zeros(work_area.size(), CV_8UC1);        
    Mat contour1_im = Mat::zeros(work_area.size(), CV_8UC1);
    Mat contour2_im = Mat::zeros(work_area.size(), CV_8UC1);
    
    //draw
    vector<vector<Point> > shifted1;
    shifted1.push_back(shift_contour(contour1, work_area.tl()));
    drawContours( contour1_im, shifted1, -1, 255, -1);
    vector<vector<Point> > shifted2;
    shifted2.push_back(shift_contour(contour2, work_area.tl()));
    drawContours( contour2_im, shifted2, -1, 255, -1);
    
    //imshow("contour1 debug", contour1_im);
    //imshow("contour2 debug", contour2_im);        
    
    if( type == 0 )
        // intersect
        bitwise_or( contour1_im, contour2_im, merged);
    else
        // unite
        bitwise_and( contour1_im, contour2_im, merged);        
    //imshow("merge contour debug", merged);
    
    // find
    vector<vector<Point> > contours;
    vector<Vec4i> hierarchy;
    findContours(merged,contours,hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE, Point(0, 0));
    
    if(contours.size() > 1){
        printf("Warn: merge_contours has output of more than one contours.");
    }
    
    return shift_contour(contours[0], work_area.tl() * -1);        
}