【问题标题】:OpenCV detect contours intersectionOpenCV检测轮廓相交
【发布时间】:2011-12-18 14:28:57
【问题描述】:

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

为了检查交叉点,我试图做一个 bitwise_and。这是抛出异常,因为输入的大小不同。我该如何解决 ?

编辑:

所附图片应该可以更好地了解该问题。汽车由蓝色轮廓跟踪,障碍物由粉红色轮廓跟踪。我需要检查十字路口。

【问题讨论】:

    标签: c++ opencv


    【解决方案1】:

    一种简单但可能不是最有效 (??) 的方法是使用 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,我会得到一个图像,轮廓相交处为 1,其他地方为 0。

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

    【讨论】:

    • 如何使用imshow()查看路口,在使用imshow显示路口时,获取到黑色图片。但是当打印交点时,如所描述的观察到的和零。是否有任何工作可以可视化交叉路口
    • @Saikrishna 使用灰度值。如果是为了可视化,请在 20... 处绘制轮廓,这是可见但不饱和的。路口会更亮(40 或更多)
    • 我认为在只绘制​​轮廓边界的情况下,有必要使用4-连通线而不是8-连通线,因为否则可能会错过某些具有特定相交角度的2条对角线的交点。跨度>
    • 当一个轮廓包含另一个轮廓时,第一个解决方案也不会检测到这种情况。
    • drawContours不是只填大纲吗?所以你会得到轮廓之间的交叉点?我必须添加cv2.FILLED 作为参数:img2 = cv2.drawContours(blank.copy(), contours, 0, 1, cv2.FILLED)
    【解决方案2】:

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

    【讨论】:

    • 这对于“压缩”轮廓是错误的,两个轮廓即使没有公共顶点也可能相交。
    • @user202729 是的。对于非压缩的 8 连接轮廓也是如此。但不适用于 4 连接。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      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);        
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-12-17
        • 2014-07-27
        • 1970-01-01
        • 2016-10-24
        • 2014-12-12
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多