Как применить матрицу к изображению

Я провел некоторый поиск, но не нашел те же самые вопросы - и решения, которые я нашел, не были адаптированы.

У меня есть изображение, представленное массивом фигуры (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 ..!

Спасибо!

1 ответ

Вы уменьшаете последнюю ось на двух входах 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
Другие вопросы по тегам