通过相似关系过滤列表

问题描述 投票:0回答:2

我有一个图像名称列表和一个(阈值)相似度矩阵。相似关系是自反的和对称的,但不是必需的传递,即,如果image_iimage_jimage_k类似,则不必表示image_jimage_k类似。

例如:

images = ['image_0', 'image_1', 'image_2', 'image_3', 'image_4']

sm = np.array([[1, 1, 1, 0, 1],
               [1, 1, 0, 0, 1],
               [1, 0, 1, 0, 0],
               [0, 0, 0, 1, 0],
               [1, 1, 0, 0, 1]])

相似度矩阵sm的解释如下:如果sm[i, j] == 1,则image_iimage_j相似,否则它们不相似。在这里我们看到image_0image_1image_2类似,但image_1image_2不相似(这只是非传递性的一个示例)。

我想保留最大数量的唯一图像(根据给定的sm矩阵,它们都是成对的非相似图像)。对于此示例,它应该是[image_2, image_3, image_4][image_1, image_2, image_3](通常有多个此类子集,但我不介意将其保留为最大长度)。我正在寻找一种有效的方法,因为我有成千上万张图片(也许没有for循环)。

编辑:以下是我的原始解决方法

np.array(images)[np.tril(sm).sum(0) == 1]

但是,不能保证它会返回最大长度子集。考虑以下示例:

sm = np.array([[1, 1, 0, 0, 0],
               [1, 1, 0, 0, 0],
               [0, 0, 1, 1, 0],
               [0, 0, 1, 1, 1],
               [0, 0, 0, 1, 1]])

此解决方案将返回['image_1', 'image_4'],而所需的结果是['image_0', 'image_2', 'image_4']['image_1', 'image_2', 'image_4']

python numpy similarity
2个回答
2
投票

据我了解,独特的图像是与其他图像不同的图像。如果是这种情况,那么我们可以汇总行(或列)并选择结果中等于1的那些元素。然后我们需要从图像列表中获取相同的元素。

目前,我不知道如何在第二步中删除循环。

[images[i] for i in np.where(sm.sum(0) == 1)[0]]

UPDATE#1

上面的讨论导致对该问题有了新的理解。

一种新的想法是一次删除一个图像,选择具有最大数量的相似图像。

images = ['image_0', 'image_1', 'image_2', 'image_3', 'image_4']

sm = np.array([[1, 1, 1, 0, 1],
               [1, 1, 0, 0, 1],
               [1, 0, 1, 0, 0],
               [0, 0, 0, 1, 0],
               [1, 1, 0, 0, 1]])

ix = list(range(len(images)))

while sm[ix].T[ix].sum() != len(ix): # exit if we got the identity matrix
  va = sm[ix].T[ix].sum(0)           # count similar images
  jx = np.argmax(va)                 # get the index of the worst image
  del ix[jx]                         # delete index of the worst image

print([images[i] for i in ix])

输出:

['image_2', 'image_3', 'image_4']

UPDATE#2

相同,但检查具有相似性最差值的每个分支

res = []

def get_wres(sm, ix):
  if sm[ix].T[ix].sum() == len(ix):
    res.append(list(ix))
    return
  va = sm[ix].T[ix].sum(0) # count similar images
  vx = np.max(va)          # get the value of the worst
  for i in range(len(ix)): # check every image
    if va[i] == vx:        # for the worst value
      ixn = list(ix)       # isolate one worst
      del ixn[i]           # image and
      get_wres(sm, ixn)    # try without it

get_wres(sm, ix)
print(res)

输出:

[[2, 3, 4], [1, 2, 3]]

1
投票

这里有一个foor循环,不确定如何做到这一点:

results = [images[i] for i in range(len(images)) if sum(sm[i][i:]) == 1]
© www.soinside.com 2019 - 2024. All rights reserved.