3

我进行了一些搜索,但没有找到完全相同的问题——而且我找到的解决方案并不适用。

我有一个图像,由一个 numpy 形状的数组表示,(l1,l2,3) 其中 l1,l2 是整数,三个是因为 RGB。

出于某种原因,我想改变基础,这意味着将矩阵 P 应用于所有 RGB 向量。请注意,P它的形状为(3,3)

我写了这个:

def change_base(Image,P):
    Image_copie=np.zeros(Image.shape)

    for i in range(Image_copie.shape[0]):
        for j in range(Image_copie.shape[1]):
            Image_copie[i,j]=np.dot(P,Image[i,j])

    return Image_copie

很明显,它可以工作,但它很丑而且非常慢。

你们有什么解决方案,也许使用 numpy ?我不使用opencv ..!

谢谢 !

4

1 回答 1

0

您正在减少两个输入Image和的最后一个轴P。所以,你可以np.tensordot像这样使用 -

np.tensordot(Image,P,axes=(-1,-1))

这也可以表示为np.dot在它之前和之后进行一些重塑,就像这样 -

Image.reshape(-1,3).dot(P.T).reshape(Image.shape[:2]+(-1,))

也可以np.einsum用于这样的归约操作,就像这样 -

np.einsum('ijk,lk->ijl',Image,P)

对于性能,作为一个单独的归约操作,没有轴对齐要求,dot-based对于大型阵列,解决方案会更快,但对于小型到体面大小的阵列,einsum可能会更好。

运行时测试

情况1 :

In [46]: # Inputs
    ...: Image = np.random.randint(0,255,(256,256,3))
    ...: P = np.random.randint(0,255,(3,3))
    ...: 

In [47]: %timeit change_base(Image,P)
    ...: %timeit np.tensordot(Image,P,axes=(-1,-1))
    ...: %timeit Image.reshape(-1,3).dot(P.T).reshape(Image.shape[:2]+(-1,))
    ...: %timeit np.einsum('ijk,lk->ijl',Image,P)
    ...: 
1 loops, best of 3: 206 ms per loop
100 loops, best of 3: 3.28 ms per loop
100 loops, best of 3: 3.22 ms per loop
100 loops, best of 3: 3.06 ms per loop

案例#2:

In [48]: # Inputs
    ...: Image = np.random.randint(0,255,(512,512,3))
    ...: P = np.random.randint(0,255,(3,3))
    ...: 

In [49]: %timeit change_base(Image,P)
    ...: %timeit np.tensordot(Image,P,axes=(-1,-1))
    ...: %timeit Image.reshape(-1,3).dot(P.T).reshape(Image.shape[:2]+(-1,))
    ...: %timeit np.einsum('ijk,lk->ijl',Image,P)
    ...: 
1 loops, best of 3: 845 ms per loop
100 loops, best of 3: 12.8 ms per loop
100 loops, best of 3: 12.7 ms per loop
100 loops, best of 3: 13.4 ms per loop
于 2016-06-13T20:02:10.917 回答