如何将矩阵应用于图像

3
我已经进行了一些搜索,但没有找到完全相同的问题 - 我找到的解决方案也无法适应。
我有一张图片,用形状为(l1,l2,3)的numpy数组表示,其中l1、l2是整数,3表示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..!

谢谢!


这是一个3x3矩阵,一个基变换矩阵。 - Gericault
那么,发布的解决方案对你有用吗? - Divakar
1个回答

0

您正在减少两个输入 ImageP 的最后一个轴。因此,您可以使用 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的解决方案会更快,但对于小到中等大小的数组,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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接