合并图像的最有效算法?
Most efficient Algorithm for merging images?
我正在寻找解决我面临的挑战的最佳算法:我有一个 K 列表列表,其中每个列表包含 N 个元素(每个列表可以包含不同数量的元素,但 0 除外)我想得到每个列表中的每个元素(从第一个开始)与以下列表中的每个元素的所有组合,因此该组合必须具有 K 个元素,并且每个组合中的每个元素必须与第 N 个元素位于相同的位置此元素来自的列表。
K 个列表的列表,其中每个列表包含 N 个元素:
[ [a1, b1, ..., N],
[a2, b2, ..., N],
....,
[aK, bK, ..., N]]
例如,对于列表:
[[a1, b1],
[a2],
[a3, b3, c3]]
组合是
a1a2a3
a1a2b3
a1a2c3
b1a2a3
b1a2b3
b1a2c3
我还应该说元素是图像,我使用 Pillow 库中的 Image.alpha_composite(img1, img2)
将它们组合在一起。所以我必须创建临时图像,它是两个图像组合的结果,然后我必须将它与下一个图像组合,再次创建临时结果,然后再次将临时图像与下一个图像组合,依此类推。
我正在寻找使用 Python 获得组合的最有效方法。提前谢谢你
我不知道是否有任何方法可以优化图像的组合,但抛开这一点,这只是一个组合问题案例,您可以使用一些非常标准的方法(包括回溯)来解决。
根据我掌握的信息,我会选择回溯,因为它可能会为您节省一些 space 和中间结果的冗余计算。
下面是一些示例代码:
def backtrack(idx, images, partial_results, results):
if idx >= len(images):
results.append(partial_results[:])
return
for image in images[idx]:
partial_results.append(image)
backtrack(idx+1, images, partial_results, results)
partial_results.pop()
images = [["a1", "b1"],["a2"], ["a3", "b3", "c3"]]
results = []
backtrack(0, images, [], results)
print(results)
## outputs
## [['a1', 'a2', 'a3'], ['a1', 'a2', 'b3'], ['a1', 'a2', 'c3'], ['b1', 'a2', 'a3'], ['b1', 'a2', 'b3'], ['b1', 'a2', 'c3']]
这种方法的好处是,如果你在这个过程中做了一些计算密集型的计算,你可以重复使用它们。
例如:['a1', 'a2', 'a3']
和['a1', 'a2', 'b3']
都在结果中,它们有一个共同的前缀。当你在将第一个添加到结果后出现递归树时,你已经从之前的计算中得到 ['a1', 'a2']
(假设它在计算上很昂贵),你可以重用它们并将 b3
与它们组合.
时间复杂度:如果我们将图像的组合部分(就像在这个简化的示例中,它只是将元素添加到列表中)视为常量操作,那么您正在执行 length of list 0 * length of list 1 *.... length of list n-1
操作,其中 n 是单个图像列表所在的外部列表的长度。如果我们将 m
视为最长列表的长度,则变为 m0 * m1 * ... * m(n-1) = m^n
Space 复杂度:递归栈的深度为n
,外层列表的长度,部分结果也不会越过n
个元素,但是最终的结果是 m^n
因为这是可能组合的数量。如果您将结果列表视为辅助 space,则 space 复杂度为 m^n
。如果不是,那就是 n
.
这是使用生成器的好地方。这是一种方法。它与任何可能的方法一样有效。其他几个也是可能的,例如可以修改 user1984。
def combinations(lists):
indices = [0] * len(lists)
while True:
yield [lists[i][j] for i, j in enumerate(indices)]
for k in reversed(range(len(lists))):
if indices[k] < len(lists[k]) - 1:
indices[k] += 1
break
indices[k] = 0
else:
return
data = [['a1', 'b1'],
['a2'],
['a3', 'b3', 'c3']]
for comb in combinations(data):
print(''.join(comb))
运行 这符合您的示例:
$ python gen.py
a1a2a3
a1a2b3
a1a2c3
b1a2a3
b1a2b3
b1a2c3
对于space,这仅使用长度为 N 的索引数组,其中 N 是输入列表的数量。每个生成列表的摊销时间为 O(1) 以增加索引。当然你还需要 O(N) 来构建每个输出列表。
这个解决方案很好,因为您永远不需要存储所有组合。它们很容易变得很大。
我正在寻找解决我面临的挑战的最佳算法:我有一个 K 列表列表,其中每个列表包含 N 个元素(每个列表可以包含不同数量的元素,但 0 除外)我想得到每个列表中的每个元素(从第一个开始)与以下列表中的每个元素的所有组合,因此该组合必须具有 K 个元素,并且每个组合中的每个元素必须与第 N 个元素位于相同的位置此元素来自的列表。
K 个列表的列表,其中每个列表包含 N 个元素:
[ [a1, b1, ..., N],
[a2, b2, ..., N],
....,
[aK, bK, ..., N]]
例如,对于列表:
[[a1, b1],
[a2],
[a3, b3, c3]]
组合是
a1a2a3
a1a2b3
a1a2c3
b1a2a3
b1a2b3
b1a2c3
我还应该说元素是图像,我使用 Pillow 库中的 Image.alpha_composite(img1, img2)
将它们组合在一起。所以我必须创建临时图像,它是两个图像组合的结果,然后我必须将它与下一个图像组合,再次创建临时结果,然后再次将临时图像与下一个图像组合,依此类推。
我正在寻找使用 Python 获得组合的最有效方法。提前谢谢你
我不知道是否有任何方法可以优化图像的组合,但抛开这一点,这只是一个组合问题案例,您可以使用一些非常标准的方法(包括回溯)来解决。
根据我掌握的信息,我会选择回溯,因为它可能会为您节省一些 space 和中间结果的冗余计算。
下面是一些示例代码:
def backtrack(idx, images, partial_results, results):
if idx >= len(images):
results.append(partial_results[:])
return
for image in images[idx]:
partial_results.append(image)
backtrack(idx+1, images, partial_results, results)
partial_results.pop()
images = [["a1", "b1"],["a2"], ["a3", "b3", "c3"]]
results = []
backtrack(0, images, [], results)
print(results)
## outputs
## [['a1', 'a2', 'a3'], ['a1', 'a2', 'b3'], ['a1', 'a2', 'c3'], ['b1', 'a2', 'a3'], ['b1', 'a2', 'b3'], ['b1', 'a2', 'c3']]
这种方法的好处是,如果你在这个过程中做了一些计算密集型的计算,你可以重复使用它们。
例如:['a1', 'a2', 'a3']
和['a1', 'a2', 'b3']
都在结果中,它们有一个共同的前缀。当你在将第一个添加到结果后出现递归树时,你已经从之前的计算中得到 ['a1', 'a2']
(假设它在计算上很昂贵),你可以重用它们并将 b3
与它们组合.
时间复杂度:如果我们将图像的组合部分(就像在这个简化的示例中,它只是将元素添加到列表中)视为常量操作,那么您正在执行 length of list 0 * length of list 1 *.... length of list n-1
操作,其中 n 是单个图像列表所在的外部列表的长度。如果我们将 m
视为最长列表的长度,则变为 m0 * m1 * ... * m(n-1) = m^n
Space 复杂度:递归栈的深度为n
,外层列表的长度,部分结果也不会越过n
个元素,但是最终的结果是 m^n
因为这是可能组合的数量。如果您将结果列表视为辅助 space,则 space 复杂度为 m^n
。如果不是,那就是 n
.
这是使用生成器的好地方。这是一种方法。它与任何可能的方法一样有效。其他几个也是可能的,例如可以修改 user1984。
def combinations(lists):
indices = [0] * len(lists)
while True:
yield [lists[i][j] for i, j in enumerate(indices)]
for k in reversed(range(len(lists))):
if indices[k] < len(lists[k]) - 1:
indices[k] += 1
break
indices[k] = 0
else:
return
data = [['a1', 'b1'],
['a2'],
['a3', 'b3', 'c3']]
for comb in combinations(data):
print(''.join(comb))
运行 这符合您的示例:
$ python gen.py
a1a2a3
a1a2b3
a1a2c3
b1a2a3
b1a2b3
b1a2c3
对于space,这仅使用长度为 N 的索引数组,其中 N 是输入列表的数量。每个生成列表的摊销时间为 O(1) 以增加索引。当然你还需要 O(N) 来构建每个输出列表。
这个解决方案很好,因为您永远不需要存储所有组合。它们很容易变得很大。