Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/typo3/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 找出给定多边形边的两个区域是否相交_Python_Opencv_Python Imaging Library_Computational Geometry_Intersection - Fatal编程技术网

Python 找出给定多边形边的两个区域是否相交

Python 找出给定多边形边的两个区域是否相交,python,opencv,python-imaging-library,computational-geometry,intersection,Python,Opencv,Python Imaging Library,Computational Geometry,Intersection,这个问题一直困扰着我一段时间了。 我确实找到了一个解决方案,我可以找到每个多边形中的每个点,然后检查交点。然而,这在计算上是昂贵的,而且根本不实用 下图中有四行;两条红线和两条蓝线。我想检查两条红线之间的区域是否与两条蓝线之间的区域相交 已知以下变量: 每行开始的点 每条线的角度 线条结束的位置(始终位于图像的边缘) 我在考虑使用斜率公式来检查红线的原点相对于每条蓝线落在哪里。但我不确定这是否是最好的方法 提前感谢。如果每种颜色都有两条线,且在图像边界上有一个共同的起点和不同的终点,则只需创建

这个问题一直困扰着我一段时间了。 我确实找到了一个解决方案,我可以找到每个多边形中的每个点,然后检查交点。然而,这在计算上是昂贵的,而且根本不实用

下图中有四行;两条红线和两条蓝线。我想检查两条红线之间的区域是否与两条蓝线之间的区域相交

已知以下变量:

  • 每行开始的点
  • 每条线的角度
  • 线条结束的位置(始终位于图像的边缘)
  • 我在考虑使用斜率公式来检查红线的原点相对于每条蓝线落在哪里。但我不确定这是否是最好的方法


    提前感谢。

    如果每种颜色都有两条线,且在图像边界上有一个共同的起点和不同的终点,则只需创建一个遮罩,绘制这些线,计算两个端点之间的中点,并将该中点用作某些整体填充的种子点。由于您有一个闭合多边形,因此该中点保证位于多边形内部。根据这两个遮罩,确定交点(逻辑与),并检查至少一个像素重叠

    下面是一些使用OpenCV和NumPy的代码:

    导入cv2
    将numpy作为np导入
    #树立形象
    w、 h=(400300)
    img=np.one((h,w,3),np.uint8)*255
    #设置颜色
    颜色={
    “红色”:(0,0255),
    “蓝色”:(255,0,0)
    }
    #设置每种颜色的线条,第一个元素是公共点
    行={
    "红色":[(200150),(380,0),(200150),(200,0)],,
    “蓝色”:[((100100),(399100)),((100100),(300,0))]
    }
    #设置每种颜色的遮罩
    面具={
    “红色”:np.0((h,w),np.uint8),
    “蓝色”:np.0((h,w),np.uint8)
    }
    #对于每种颜色。。。
    对于['Red','Blue']中的c:
    对于第[c]行中的第行:
    # ... 在图像中画彩色线。。。
    img=cv2.行(img,行[0],行[1],颜色[c],2)
    # ... 在面具上画白线。。。
    掩码[c]=cv2.行(掩码[c],行[0],行[1],255,1)
    # ... 找到两个端点之间的中点,然后。。。
    mid=tuple(np.int0(np.sum(np.array(lines[c])[:,1,:],axis=0)/2))
    # ... 使用中点作为种子点的整体填充遮罩
    遮罩[c]=cv2.泛洪填充(遮罩[c],无,中,255)[1]
    #逻辑和所有遮罩,并检查至少一个像素重叠
    inter=np.all(np.array(list(masks.values())),axis=0.astype(np.uint8)*255
    打印('Is intersection:',inter.max()>0)
    #输出
    cv2.imshow(“图像”,img)
    cv2.imshow('红色遮罩',遮罩['红色']))
    cv2.imshow(“蓝色遮罩”,遮罩[“蓝色”])
    cv2.imshow(“交叉口”,中间)
    cv2.等待键(0)
    cv2.destroyAllWindows()
    
    图片:

    红色面具:

    蓝色面具:

    交叉口:

    intersection = np.logical_and(red_poly, blue_poly)
    # plt.imshow(intersection)
    

    决定:

    是否为交点:True
    
    该代码可以很容易地推广到添加更多的颜色(或多边形)

    ----------------------------------------
    系统信息
    ----------------------------------------
    平台:Windows-10-10.0.16299-SP0
    Python:3.9.1
    皮查姆:2021.1
    NumPy:1.20.2
    OpenCV:4.5.1
    ----------------------------------------
    
    解决此问题主要有两种方法:

    1.线性规划 将问题表示为线性不等式组,并将其作为线性规划问题求解,如下所述:。在你的例子中,不等式的形式是
    (x-ox[i])*sin(a[i])-(y-oy[i])*cos(a[i])>0
    (x-ox[i])*sin(a[i])-(y-oy[i])*cos(a[i])<0
    ,这取决于你如何定义第i条线的角度
    a[i]
    ,以及该线的哪一侧放置多边形<代码>(ox[i],oy[i])是第i个顶点的坐标。如果不等式严格与否,则取决于如何处理多边形与顶点或边接触的边界情况。这是一个很好的、易于推广的方法,但它可能很慢

    2.交叉测试 在一般情况下(没有顶点和边重合),有4种可能性:(1)一些边相交;(2) 多边形1在多边形2内;(3) 多边形2在多边形1内;(4) 多边形不相交。您需要测试前3个案例

    对于案例1,您需要执行此处所述的线段相交测试,并尝试将多边形1的每条边与多边形2的每条边相交,这在您的案例中不是问题,因为最多会有
    2*2=4
    测试。如果检测到至少一个交叉口,则完成

    对于情况2和3,需要测试多边形1的顶点是否在多边形2内,反之亦然。可以使用中所述的相同测试
    IsOnLeft
    IsOnRight
    :如果一个点位于右线的左侧和左线的右侧,则该点位于内部


    在任何情况下,都应该特别注意退化和边界情况:如果多边形的边重合,或者一个多边形的顶点位于另一个多边形的边上,或者不同多边形的边重合,该怎么办。根据您的特殊目的,您可能会对此类情况进行不同的检测和处理。

    这是一个使用小型单通道图像10x10像素的示例

    basic_img = np.zeros([10, 10], dtype=np.uint8)
    
    一旦你有了点的坐标,让我们说:

    pts_red = np.array([(9, 0), (9, 6), (4, 2), (4, 0)], dtype=np.int32)
    pts_blue = np.array([(9, 0), (9, 1), (0, 8), (6, 0)], dtype=np.int32)
    
    可以使用绘制线之间包含的多边形:

    red_poly = basic_img.copy()
    cv2.fillPoly(red_poly, [pts_red], 1)
    # plt.imshow(red_poly)
    

    然后使用以获取交叉点:

    intersection = np.logical_and(red_poly, blue_poly)
    # plt.imshow(intersection)
    
    最后,检查任何真值以获得布尔结果:

    np.any(intersection) #=> True
    

    这里是本例的打印图像。 蓝色保利

    红色保利

    十字路口


    这里有一个枕头版本的,包含了相同的想法。然而,此版本仅限于两种颜色。添加更多颜色(或多边形)需要额外的工作(基本上是一些循环)

    从PIL导入Ima
    
    import cv2
    import numpy as np
    
    def intersected(img, masks):
        img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        for lower, upper in masks:
            mask = cv2.inRange(img_hsv, np.array(lower), np.array(upper))
            blur = cv2.GaussianBlur(mask, (5, 5), 0)
            canny = cv2.Canny(blur, 0, 0)
            contours, _ = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
            count = 0
            for cnt in contours:
                if cv2.contourArea(cnt) > 50:
                    cv2.drawContours(img, [cnt], -1, (0, 255, 0), 1)
                    cv2.imshow("Test", img)
                    count += 1
                    if count == 2:
                        return True
    
    img = cv2.imread("shapes.png")
    
    blue_mask = [1, 0, 0], [178, 255, 255]
    red_mask = [0, 1, 0], [179, 254, 255]
    
    if intersected(img, (blue_mask, red_mask)):
        print("Intersection detected!")
    else:
        print("No intersection detected.")
    
    Intersection detected!
    
    import cv2
    import numpy as np
    
    def intersected(img, masks):
    
        img_hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
        for lower, upper in masks:
            mask = cv2.inRange(img_hsv, np.array(lower), np.array(upper))
    
            blur = cv2.GaussianBlur(mask, (5, 5), 0)
            canny = cv2.Canny(blur, 0, 0)
            contours, _ = cv2.findContours(canny, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE)
    
            count = 0
            for cnt in contours:
                if cv2.contourArea(cnt) > 50:
                    cv2.drawContours(img, [cnt], -1, (0, 255, 0), 1)
                    cv2.imshow("Test", img)
                    count += 1
                    if count == 2:
                        return True
    
    img = cv2.imread("shapes.png")
    
    blue_mask = [1, 0, 0], [178, 255, 255]
    red_mask = [0, 1, 0], [179, 254, 255]
    
    if intersected(img, (blue_mask, red_mask)):
        print("Intersection detected!")
    else:
        print("No intersection detected.")