如何将多边形裁剪到矩形区域内
How to crop polygon to be within a rectangular region
所以我有一个形状为 (N, 2)
的 numpy
多边形数组,我想对其进行裁剪,使其位于 1 中看到的 256x256
图像的范围内.也就是说,我想裁剪这个多边形,使其与 256x256
区域内黄色蒙版的边界相匹配;输出多边形的面积应等于此遮罩且形状为 (Mx2)
.
如图所示,我已经将多边形栅格化以创建二进制掩码,使其位于边界 256x256
内。但是,我还想裁剪多边形,使其与二进制掩码的边界相匹配。我怎样才能做到这一点?我正在考虑通过创建一个矩形多边形 [(0,0), (0,256), (256,256), (256,0)]
来使用 shapely
来实现它,但是,我意识到可能有很多我必须处理的边缘情况:
- 盒子与多边形相交,因此,我们要得到相交的多边形
- 盒子完全在多边形内部,因此输出盒子
- 多边形完全在框内,因此,输出原始多边形
- 相交产生多个多边形,需要处理这个
也许编写一些代码来处理所有这些事情并没有那么糟糕,但是是否有某种库可以快速轻松地做到这一点?
Shapely 可以很好地解决您的问题。您的边缘情况是两个通用多边形相交的标准情况,您可以使用 Polygon.intersection
(link)。如果相交产生多个多边形,那么 Polygon.intersection
只会给你一个 MultiPolygon
。这里有一个例子来说明:
from shapely.geometry import Polygon
from shapely.affinity import scale,translate
import matplotlib.pyplot as plt
import numpy as np
# build squiggly polygon
theta=np.linspace(0,2*np.pi,100)
x=np.cos(theta)+0.1*np.sin(theta*10)
y=np.sin(theta)
A=Polygon(np.column_stack((x,y)))
# build a box
B=Polygon([[-.25,-1.5],[.25,-1.5],[.25,1.25],[-.25,1.25],[-.25,-1.5]])
# Intersection
C=A.intersection(B)
plt.subplot(2,2,1)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B.boundary.xy[0],B.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('standard intersection')
# box in squiggly
B1=scale(B,0.5,0.5)
C=A.intersection(B1)
plt.subplot(2,2,2)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('box in squiggly')
# squiggly in box
B1=scale(B,5,5)
C=A.intersection(B1)
plt.subplot(2,2,3)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('squiggly in box')
# multipolygons
B1=translate(B,1.2,0)
C=A.intersection(B1)
plt.subplot(2,2,4)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
for poly in C:
plt.plot(poly.boundary.xy[0],poly.boundary.xy[1],'--r',label='C')
plt.title('multipolygons')
plt.show()
产生下图
所以我有一个形状为 (N, 2)
的 numpy
多边形数组,我想对其进行裁剪,使其位于 1 中看到的 256x256
图像的范围内.也就是说,我想裁剪这个多边形,使其与 256x256
区域内黄色蒙版的边界相匹配;输出多边形的面积应等于此遮罩且形状为 (Mx2)
.
如图所示,我已经将多边形栅格化以创建二进制掩码,使其位于边界 256x256
内。但是,我还想裁剪多边形,使其与二进制掩码的边界相匹配。我怎样才能做到这一点?我正在考虑通过创建一个矩形多边形 [(0,0), (0,256), (256,256), (256,0)]
来使用 shapely
来实现它,但是,我意识到可能有很多我必须处理的边缘情况:
- 盒子与多边形相交,因此,我们要得到相交的多边形
- 盒子完全在多边形内部,因此输出盒子
- 多边形完全在框内,因此,输出原始多边形
- 相交产生多个多边形,需要处理这个
也许编写一些代码来处理所有这些事情并没有那么糟糕,但是是否有某种库可以快速轻松地做到这一点?
Shapely 可以很好地解决您的问题。您的边缘情况是两个通用多边形相交的标准情况,您可以使用 Polygon.intersection
(link)。如果相交产生多个多边形,那么 Polygon.intersection
只会给你一个 MultiPolygon
。这里有一个例子来说明:
from shapely.geometry import Polygon
from shapely.affinity import scale,translate
import matplotlib.pyplot as plt
import numpy as np
# build squiggly polygon
theta=np.linspace(0,2*np.pi,100)
x=np.cos(theta)+0.1*np.sin(theta*10)
y=np.sin(theta)
A=Polygon(np.column_stack((x,y)))
# build a box
B=Polygon([[-.25,-1.5],[.25,-1.5],[.25,1.25],[-.25,1.25],[-.25,-1.5]])
# Intersection
C=A.intersection(B)
plt.subplot(2,2,1)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B.boundary.xy[0],B.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('standard intersection')
# box in squiggly
B1=scale(B,0.5,0.5)
C=A.intersection(B1)
plt.subplot(2,2,2)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('box in squiggly')
# squiggly in box
B1=scale(B,5,5)
C=A.intersection(B1)
plt.subplot(2,2,3)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
plt.plot(C.boundary.xy[0],C.boundary.xy[1],'--r',label='C')
plt.title('squiggly in box')
# multipolygons
B1=translate(B,1.2,0)
C=A.intersection(B1)
plt.subplot(2,2,4)
plt.plot(A.boundary.xy[0],A.boundary.xy[1],'k',label='A')
plt.plot(B1.boundary.xy[0],B1.boundary.xy[1],'b',label='B')
for poly in C:
plt.plot(poly.boundary.xy[0],poly.boundary.xy[1],'--r',label='C')
plt.title('multipolygons')
plt.show()
产生下图