繁体   English   中英

将每个第一个子列表与 rest 进行比较,如果它们通过条件,则将列表中的第二个子列表分组

[英]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 数据分组? 在此处输入图像描述

文件1 文件2

这是一个有趣的问题,因为有一些曲线球。 首先,您不是在寻找重叠的矩形,而是在寻找矩形 您想要的结果暗示了这一点。 我试图在下面的代码中明确说明:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM