This article is participating in Python Theme Month. See the link to the event for more details

[toc]

Introduction to the

This article will show you how to perform linear algebraic operations on multidimensional data in NumPy in graphical form.

Linear algebra of multidimensional data is usually used in image processing in graph transformation, this article will use an image example to illustrate.

Graphic loading and description

If you’re familiar with colors, you know that A color can be denoted by R, G, B, or, if you’re A little more advanced, A for transparency. Usually we use an array of four properties.

For a two-dimensional image, its resolution can be regarded as an X*Y matrix, and the color of each point in the matrix can be represented by (R, G, B).

With this knowledge, we can decompose the color of the image.

First we need to load an image. We use the imageio.imread method to load a local image, as shown below:

import imageio
img=imageio.imread('img.png')
print(type(img))
Copy the code

The above code reads the image locally into the IMG object, using type to see the type of IMG. From the run result, we can see that the type of IMG is an array.

class 'imageio.core.util.Array'

Copy the code

Img is A three-dimensional array of (80, 170, 4), that is, the resolution of the image is 80*170, and each pixel is an array of (R, B, G, A).

Finally, the image is drawn as follows:

import matplotlib.pyplot as plt
plt.imshow(img)

Copy the code

Grayscale of figure

For a three-dimensional array, we can get an array of three colors as follows:

red_array = img_array[:, :, 0]
green_array = img_array[:, :, 1]
blue_array = img_array[:, :, 2]
Copy the code

With three colors we can use the following formula to grayscale them:

Y= 0.2126r + 0.7152g + 0.0722bCopy the code

The Y in the figure above is grayscale.

How do we use matrix multiplication? Just use @ :

Img_gray = img_array @ [0.2126, 0.7152, 0.0722]Copy the code

Now IMG is an 80 by 170 matrix.

Now use cmap=”gray” to draw:

plt.imshow(img_gray, cmap="gray")
Copy the code

The following grayscale image can be obtained:

Compression of grayscale images

Gray image is to transform the color of the image, if you want to compress the image how to deal with it?

There’s a concept in matrix operations called singular values and eigenvalues.

Let A be A matrix of order n, if A constant λ and an n-dimensional non-zero vector x exist such that Ax is equal to λx, then lambda is said to be the eigenvalue of A, and x is the eigenvector of A belonging to the eigenvalue λ.

A set of eigenvectors of a matrix is a set of orthogonal vectors.

That is, if you apply A linear transformation to the eigenvector A it just makes the vector elongate or shorten without changing its direction.

Eigendecomposition, also known as Spectral decomposition, is the decomposition of matrices into the product of matrices represented by their eigenvalues and eigenvectors.

If A is A matrix of order m by n, q=min(m,n), the arithmetic square root of q non-negative eigenvalues of A*A is called the singular values of A.

Eigenvalue decomposition is a convenient way to extract the features of a matrix, but only if the matrix is a square matrix. In the case of non-square matrices, you have to use singular value decomposition. Let’s take a look at the definition of singular value decomposition:


A = U Σ V T A = U Σ V ^ T

Where A is the m * n matrix that we want to decompose, U is an m * m square matrix, σ is an m * n matrix, and all the non-diagonal elements are 0. VTV to the TVT is V transpose, which is also an n by n matrix.

Similar to the eigenvalues, singular values are arranged from large to small in the matrix σ, and the reduction of singular values is particularly rapid. In many cases, the sum of the top 10% or even 1% of singular values accounts for more than 99% of the sum of all singular values. In other words, we can also approximate the matrix in terms of singular values that are larger than r. R is a number much smaller than m and n, so you can compress the matrix.

With singular value decomposition, we can approximately replace the original matrix with a smaller amount of data.

To use SVD, you can directly call linalg. SVD as follows:

U, s, Vt = linalg.svd(img_gray)
Copy the code

Where U is an m by m matrix and Vt is an n by n matrix.

In the above image, U is a matrix of (80, 80) and Vt is a matrix of (170, 170). S is an array of 80, and s contains the singular values in IMG.

If s is represented by an image, we can see that most of the singular values are concentrated in the former part:

That means we can take the first part of s to reconstruct the image.

For image reconstruction using S, it is necessary to restore S to an 80 * 170 matrix:

Import numpy as np Sigma = np.zeros((80, 170)) for I in range(80): Sigma[I, I] = s[I] import numpy as NP Sigma = NP.zeros ((80, 170)) for I in range(80): Sigma[I, I] = s[I]Copy the code

The original matrix can be reconstructed using u@sigma@vt, and the difference between the original matrix and the reconstructed matrix can be compared by calculating linalg. Norm.

linalg.norm(img_gray - U @ Sigma @ Vt)

Copy the code

Or use Np. allclose to compare the difference between two matrices:

np.allclose(img_gray, U @ Sigma @ Vt)
Copy the code

Or just take the first 10 elements of the s array and redraw it to compare the difference with the original:

k = 10
approx = U @ Sigma[:, :k] @ Vt[:k, :]
plt.imshow(approx, cmap="gray")
Copy the code

As you can see, the difference is not that great:

Compression of the original image

In the last video we talked about how to compress a grayscale image, so how to compress the original image?

The matrix can also be decomposed using linalg.svd.

However, some processing is required before use, because the imG_array of the original image is a matrix of (80, 170, 3) — here we have removed the transparency, leaving only the R, B, and G attributes.

(index=2, index=0); (index=0, index=0); (index=0, index=0);

img_array_transposed = np.transpose(img_array, (2, 0, 1))
print(img_array_transposed.shape)

U, s, Vt = linalg.svd(img_array_transposed)
print(U.shape, s.shape, Vt.shape)

Copy the code

Similarly, now S is a matrix of (3, 80), which is still missing one dimension. If the image is reconstructed, it needs to be filled and processed, and finally the reconstructed image will be output:

Sigma = np.zeros((3, 80, 170))

for j in range(3):
    np.fill_diagonal(Sigma[j, :, :], s[j, :])

reconstructed = U @ Sigma @ Vt
print(reconstructed.shape)

plt.imshow(np.transpose(reconstructed, (1, 2, 0)))

Copy the code

Of course, the preceding K eigenvalues can also be selected to compress the image:

approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]
print(approx_img.shape)
plt.imshow(np.transpose(approx_img, (1, 2, 0)))

Copy the code

The reconstructed image is as follows:

By comparison, we can find that the image is still distinguishable despite the loss of some accuracy.

conclusion

There are a lot of linear operations involved in changing the image, and you can take this article as an example and study it carefully.

This article is available at www.flydean.com/08-python-n…

The most popular interpretation, the most profound dry goods, the most concise tutorial, many you do not know the small skills waiting for you to find!

Welcome to follow my public number: “procedures those things”, understand technology, more understand you!