[英]Compare each first sublist with the rest and group the second sublist from the list if they pass condition
我的输入数据是
mylist = [[[1820, 57, 1920, 237], [2, 3, 3]], [[1830, 90, 1920, 240], [2, 3, 4]], [[1450, 0, 1667, 197], [1, 3, 6]], [[1835, 90, 1920, 240], [0, 5, 7]],[[1452, 0, 1667, 197], [9, 9, 9]]]
我有一组矩形数据,第一个子列表包含其坐标,第二个子列表包含 rgb 数据。 如果它们重叠,我想对第二个子列表进行分组。 下面是检查矩形是否重叠的代码。
def isRectangleOverlap(self, R1, R2):
if (R1[0] >= R2[2]) or (R1[2] <= R2[0]) or (R1[3] <= R2[1]) or (R1[1] >= R2[3]):
return False
else:
return True
我有以下代码:
for i in range(len(mylist)):
for j in range(i + 1, len(mylist)):
if isRectangleOverlap(mylist[i][0], mylist[j][0]):
....
如果他们通过条件,第二个子列表将被组合在一起。
我预期的 output:
[[[2, 3, 3], [2, 3, 4], [0, 5, 7]], [[1, 3, 6], [9, 9, 9]]]
你有什么建议吗?
更新:我用下面的答案解决了这个问题,但我还有另一个问题,是否可以将像这样聚集在一个小区域中的 retangle 的 RGB 数据分组?
这是一个有趣的问题,因为有一些曲线球。 首先,您不是在寻找重叠的矩形,而是在寻找矩形簇。 您想要的结果暗示了这一点。 我试图在下面的代码中明确说明:
mylist = [[[1820, 57, 1920, 237], [2, 3, 3]], [[1830, 90, 1920, 240], [2, 3, 4]], [[1450, 0, 1667, 197], [1, 3, 6]], [[1835, 90, 1920, 240], [0, 5, 7]],[[1452, 0, 1667, 197], [9, 9, 9]]]
# R= [Ly, Lx, Ry, Rx] = (LowerLeft-Y, LowerLeft-X, UpperRight-Y, UpperRight-X)
clusters = {}
#will hold end results, clustering overlapping rectangels together by key in mylist
#{
# 1: [1,2]
#}
def isRectangleOverlap(R1: list, R2: list):
if (R1[0] >= R2[2]) or (R1[2] <= R2[0]) or (R1[3] <= R2[1]) or (R1[1] >= R2[3]):
return False
else:
return True
def hasAlreadyOverlapped(key: int):
for k, v in clusters.items():
if key in v:
return k
return None
#itterate over every set of Rectangle,RGB combination
for i in range(len(mylist)):
cur_rect = mylist[i][0]
current_cluster = None
#check if current rectangle has already overlapped with previous rectangles,
#and if so, any new overlappings with current rectangle will be added to that cluster
#otherwise a new cluster will be created with current index i
current_cluster = hasAlreadyOverlapped(i) or i+1
#if this is a new cluster, then initiate it with current rectange in it
if not (current_cluster in clusters):
clusters[current_cluster] = [i]
#check remaining rectangles in mylist for overlapping, and add them to current cluster
#unless of course, if this is the last item.
if i < len(mylist)-1:
for j in range(i+1, len(mylist)):
if isRectangleOverlap(cur_rect, mylist[j][0]):
#this rectangle could already overlapped with a previouws processed rectangle, so we
#need to check for that.
if not (j in clusters[current_cluster]):
clusters[current_cluster].append(j)
print(clusters)
#> {1: [0, 1, 3], 3: [2, 4]}
result = []
for _, rectangles in clusters.items():
c = []
for i in rectangles:
c.append(mylist[i][1])
result.append(c)
print(result)
#> [[[2, 3, 3], [2, 3, 4], [0, 5, 7]], [[1, 3, 6], [9, 9, 9]]]
请注意,这里有一个问题我没有考虑到。 比方说,rect0 和 rect8 重叠,rect3 和 rect4 重叠。 上面的代码将创建集群。 但是,如果两个集群都与 rect9 重叠(rect9 在 rect8 和 rect3 上延伸)怎么办?
今天晚些时候我会再考虑一下,有趣的问题!
更新我又花了一点时间考虑它,我想出了一个更好的解决方案,使用递归。 如前所述,上述解决方案遍历矩形并查看是否有任何重叠(创建集群)。 然而,当遇到桥接矩形时,两个独立的集群不能在以后合并。 为了抵消这种影响,逻辑是当你找到一个集群时探索一个集群,并且在你用完当前的重叠矩形集群之后,你继续移动到形成新集群的新矩形。
请参阅下面的代码,为了便于阅读,我做了一些修改(例如为矩形创建了一个 class)。
class Rectangle():
"""
Making the objects in your list a bit more readable
"""
def __init__(self, lleft_y: int, lleft_x: int, uright_y:int, uright_x:int, rgb: list) -> None:
self.lleft_y = lleft_y
self.lleft_x = lleft_x
self.uright_y = uright_y
self.uright_x = uright_x
self.rgb = rgb
mylist = [
Rectangle(1820, 57, 1920, 237, [2, 3, 3]),
Rectangle(1830, 90, 1920, 240, [2, 3, 4]),
Rectangle(1450, 0, 1667, 197, [1, 3, 6]),
Rectangle(1835, 90, 1920, 240, [0, 5, 7]),
Rectangle(1452, 0, 1667, 197, [9, 9, 9])]
# This list will hold all clusters of overlapping rectangles by their index
clusters: list[list[int]] = []
# This list will keep track of all already processed rectangles by their index
processed_rectangles: list[int] = []
def doRectanglesOverlap(R1: Rectangle, R2: Rectangle):
# if (R1 above of R2) or (R1 below of R2) or (R1 left of R2) or (R1 right of R2)
if (R1.lleft_y >= R2.uright_y) or (R1.uright_y <= R2.lleft_y) or (R1.uright_x <= R2.lleft_x) or (R1.lleft_x >= R2.uright_x):
return False
else:
return True
def find_overlapping(index: int) -> list[int]:
# First find all rectangles directly overlapping with current rectangle
result: list[int] = []
for j in range(len(mylist)):
# If this rectangle was already processed because it was part of another cluster, just skip it
if j in processed_rectangles:
continue
if doRectanglesOverlap(mylist[index], mylist[j]):
processed_rectangles.append(j)
result.append(j)
# Now, for each found overlapping rectangle, we want to find the overlapping rectangles as well,
# effectively exploring the cluster outward. Recursive functions can be handy!
for r in result:
result += find_overlapping(r)
return result
# Looping over all rectangles
for i in range(len(mylist)):
# If this rectangle was already processed because it was part of another cluster, just skip it
if i in processed_rectangles:
continue
processed_rectangles.append(i)
# If it was not part of another earlier processed cluster, it is a new cluster. Let's add it.
current_cluster = [i]
# Now, we are going to loop over all remaining rectangles that haven't been processed yet, and add it to the current cluster
other_rectangles = find_overlapping(i)
# Due to the recursion, `other_rectangles` now hold the entire rest of the cluster.
current_cluster = current_cluster + (other_rectangles)
clusters.append(current_cluster)
print(clusters)
#> [[0, 1, 3], [2, 4]]
result = []
for ix, cluster in enumerate(clusters):
result.append([])
for i in cluster:
result[ix].append(mylist[i].rgb)
print(result)
#> [[[2, 3, 3], [2, 3, 4], [0, 5, 7]], [[1, 3, 6], [9, 9, 9]]]
将找到的项目设置为空列表的简单版本。 这不是很有效,因为要比较的列表不会变短。
import copy
mylist = [[[1820, 57, 1920, 237], [2, 3, 3]], [[1830, 90, 1920, 240], [2, 3, 4]], [[1450, 0, 1667, 197], [1, 3, 6]], [[1835, 90, 1920, 240], [0, 5, 7]],[[1452, 0, 1667, 197], [9, 9, 9]]]
def isRectangleOverlap(R1, R2):
if (not R1) or (not R2):
return False
if (R1[0] >= R2[2]) or (R1[2] <= R2[0]) or (R1[3] <= R2[1]) or (R1[1] >= R2[3]):
return False
else:
return True
mylist2 = copy.deepcopy(mylist)
grouped = []
for i in range(len(mylist)):
grouped.append([])
for j in range(i + 1, len(mylist)):
if isRectangleOverlap(mylist[i][0], mylist2[j][0]):
if not grouped[i]: # include the i'th sublist
grouped[i].append(mylist[i][1])
grouped[i].append(mylist[j][1])
mylist2[j] = [[], []]
grouped = [sublst for sublst in grouped if sublst]
print(grouped)
从列表中删除项目以便不再检查它们的更复杂的方法:
mylist2 = copy.deepcopy(mylist)
grouped = []
for i in range(len(mylist)):
grouped.append([])
inds_2_remove = []
for j in range(len(mylist2)):
if mylist[i] == mylist2[j]:
inds_2_remove.append(j)
continue
if isRectangleOverlap(mylist[i][0], mylist2[j][0]):
if not grouped[i]:
grouped[i].append(mylist[i][1])
grouped[i].append(mylist2[j][1])
inds_2_remove.append(j)
for ind_2_remove in reversed(inds_2_remove):
print(ind_2_remove)
del mylist2[ind_2_remove]
grouped = [sublst for sublst in grouped if sublst]
print(grouped)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.