遍历数据框并删除行

时间:2020-05-07 09:20:11

标签: python

我想检测2D平面中的矩形碰撞(图片)。我的图片中可以有很多矩形。

我将矩形坐标存储在如下所示的数据框中:

enter image description here

每行对应一个矩形。 proba是我的机器学习模型的结果

我想遍历每条线,检查矩形是否与另一矩形共享坐标。如果答案是肯定的,我想检查两个矩形的概率,并删除概率最低的那个矩形

我已经具有碰撞检测功能(不确定它是否已100%正常工作,我稍后再检查)

def collision(x1,y1,w1,h1,x2,y2,w2,h2):
    if (x1<= x2+w2 and x1+w1>= x2 and y1 <= y2+h2 and  y1+h1 >= y2):
        return True
    else:
        return False

现在,如何遍历我的数据框并以最低的概率删除碰撞的矩形?

感谢帮助

编辑:对于上面的示例,伪代码会这样

Collision(line1,line2) > result = True > remove line 1

Now we have only 3 line 


Collision(line1,line2) > result = False > Do Nothing

Collision(line1,line3) > result = True> remove line3



EDIT2:添加可复制的示例

#create data frame
fake_data=pd.DataFrame()
fake_data["left"]=(0.04,0.1,0.4,0.3)
fake_data["top"]=(0.31,0.13,0.34,0.28)
fake_data["width"]=(0.82,0.7,0.82,0.84)
fake_data["height"]=(0.57,0.2,0.59,0.55)
fake_data["proba"]=(0.60,0.62,0.34,0.39)

#define function
def collision(x1,y1,w1,h1,x2,y2,w2,h2):
    if (x1<= x2+w2 and x1+w1>= x2 and y1 <= y2+h2 and  y1+h1 >= y2):
        return True
    else:
        return False

#example how to use function

collision(fake_data.iloc[3,0],fake_data.iloc[3,1],fake_data.iloc[3,2],fake_data.iloc[3,3],fake_data.iloc[1,0],fake_data.iloc[1,1],fake_data.iloc[1,2],fake_data.iloc[1,3])


1 个答案:

答案 0 :(得分:1)

您的问题定义不明确。请考虑以下内容:

矩形1与矩形2碰撞,而不是与矩形3碰撞。

矩形2与矩形3碰撞。

它们的概率是矩形1>矩形2>矩形3

由于矩形2的概率高于矩形3的概率,因此是否删除矩形3,尽管一旦由于与矩形1的碰撞而删除了矩形2,矩形3就不会发生碰撞? 通过简单地遍历数据框,您可能最终会删除比实际需要更多的矩形。

如果您不关心这个事实,下面的脚本将迅速获得您想要的结果:

def func(coordinates):  # function to find collisions with all other rows for a given row
    collisions = fake_data.apply(lambda row: (collision(*row[:-1], *coordinates[:-1]) == True), axis=1)  # this finds collisions
    collisions_w_lower_prob = [i for i, x in enumerate(collisions) if fake_data.iloc[i]['proba']< coordinates['proba']]  # this saves those collision rows that had a lower probability
    return collisions_w_lower_prob

to_delete = fake_data.apply(lambda row: func(row), axis=1).values  # apply said function to your dataframe so all rows are compared to all other rows
to_delete_unique = set([y for z in to_delete for y in z]) #unique indices to delete
fake_data.drop(to_delete_unique)
>>> left    top   width   height  proba
    0.1    0.13    0.7     0.2    0.62

如果您愿意的话,则需要从概率最高的矩形开始以迭代方式删除:

fake_data = fake_data.sort_values('proba', ascending=False)  # we want to start with higher probabilities first, as they are guaranteed to stay.

idx = 0
while True:
    curr_row = fake_data.iloc[0]
    to_delete = func(curr_row)  # get deletion candidates
    fake_data.drop(to_delete, inplace=True)  # drop them from your dataframe
    idx += 1
    if idx > len(fake_data):
        break

fake_data
>>> left    top   width   height  proba
    0.1    0.13    0.7     0.2    0.62

请注意,在您的示例中,两种方法均会产生相同的结果,但是由于所解释的原因,情况可能并非总是如此。