NumPy 는 다 차원 배열 의 선형 대 수 를 실현 합 니 다.

간단 한 소개
본 고 는 도표 의 형식 으로 NumPy 에서 다 차원 데이터 의 선형 대수 연산 을 어떻게 하 는 지 설명 할 것 이다.
다 차원 데이터 의 선형 대 수 는 보통 이미지 처리 의 도형 변환 에 사용 되 는데 본 고 는 이미지 의 예 를 들 어 설명 할 것 이다.
그래 픽 로드 및 설명
색깔 을 잘 아 는 분 들 은 다 아 실 거 예요.한 색깔 은 R,G,B 로 표시 할 수 있어 요.조금 더 고 급 스 러 우 면 A 로 투명 도 를 표시 할 수 있어 요.보통 우 리 는 네 개의 속성의 배열 로 표시 한다.
2 차원 이미지 의 경우 해상 도 는 X*Y 의 행렬 로 볼 수 있 고 행렬 의 모든 점 의 색 은(R,G,B)로 표시 할 수 있다.
위의 지식 이 있 으 면 우 리 는 이미지 의 색깔 을 분해 할 수 있다.
먼저 그림 을 불 러 와 야 합 니 다.저 희 는 imageio.imread 방법 으로 로 컬 그림 을 불 러 옵 니 다.다음 과 같 습 니 다.

import imageio
img=imageio.imread('img.png')
print(type(img))
위의 코드 는 로 컬 에서 그림 을 읽 고 img 대상 으로 이동 합 니 다.type 을 사용 하면 img 의 종 류 를 볼 수 있 습 니 다.실행 결과 에서 img 의 종 류 는 배열 임 을 볼 수 있 습 니 다.

class 'imageio.core.util.Array'
img.shape 를 통 해 img 은 하나의(80,170,4)3 차원 배열 임 을 얻 을 수 있 습 니 다.즉,이 이미지 의 해상 도 는 80*170 이 고 각 픽 셀 은 하나의(R,B,G,A)배열 입 니 다.
마지막 으로 그림 을 다음 과 같이 그립 니 다.

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

도형 의 그 레이스 케 일
3 차원 배열 에 있어 우 리 는 세 가지 색깔 의 배열 을 다음 과 같이 얻 을 수 있다.

red_array = img_array[:, :, 0]
green_array = img_array[:, :, 1]
blue_array = img_array[:, :, 2]
세 가지 색깔 이 생 긴 후에 우 리 는 아래 의 공식 을 사용 하여 그 레이스 케 일 을 바 꿀 수 있다.

Y=0.2126R + 0.7152G + 0.0722B
위의 그림 에서 Y 는 그 레이스 케 일 을 나타 낸다.
행렬 의 곱셈 을 어떻게 사용 합 니까?@을 사용 하면 됩 니 다:

 img_gray = img_array @ [0.2126, 0.7152, 0.0722]
현재 img 은 80*170 의 행렬 입 니 다.
현재 cmap="gray"를 사용 하여 그림 을 그립 니 다:

plt.imshow(img_gray, cmap="gray")
다음 그 레이스 케 일 그림 을 얻 을 수 있 습 니 다:

그 레이스 케 일 압축
그 레이스 케 일 그림 은 그림 의 색 을 바 꾸 는 것 입 니 다.그림 을 압축 하려 면 어떻게 처리 해 야 합 니까?
행렬 연산 에는 기이 한 값 과 특징 값 이라는 개념 이 있다.
A 를 n 단계 행렬 로 설정 하고 상수 가 있 으 면λ그리고 n 차원 비 0 벡터 x,Ax=λxλ행렬 A 의 특징 값 이 고 x 는 A 가 특징 값 에 속한다.λ의 특징 벡터.
행렬 의 특징 벡터 는 정교 벡터 이다.
즉,특징 벡터 가 선형 변환 A 를 사용 하면 벡터 가 늘 어 나 거나 짧 아 질 뿐 그 방향 은 변 하지 않 는 다.
특징 분해(Eigendecomposition)는 스펙트럼 분해(Spectral decomposition)라 고도 부 르 며 행렬 을 특징 값 과 특징 벡터 로 분해 하여 행렬 의 적 을 나타 내 는 방법 이다.
만약 A 가 m*n 단계 행렬 이 라면 q=min(m,n),A*A 의 q 개 비 마이너스 특징 값 의 산술 제곱 근 을 A 의 기이 한 값 이 라 고 합 니 다.
특징 치 분 해 는 행렬 의 특징 을 편리 하 게 추출 할 수 있 지만 전 제 는 이 행렬 이 방진 이라는 것 이다.비 방진 의 경우 기이 한 값 으로 분해 해 야 한다.먼저 기이 한 값 분해 의 정 의 를 보십시오:
A=UΣVT
그 중에서 A 는 목표 가 분해 해 야 할 m*n 의 행렬 이 고 U 는 m*m 의 방진 이다.Σ m*n 의 행렬 로 대각선 이 아 닌 요 소 는 모두 0 입 니 다.VTV^TVT 는 V 의 전환 이자 n*n 의 행렬 입 니 다.
기이 한 값 은 특징 값 과 유사 하 며 행렬 에 있 습 니 다.Σ중 역시 큰 것 에서 작은 것 으로 배열 되 고 기이 한 값 의 감소 가 특히 빠르다.많은 경우 에 앞의 10%,심지어 1%의 기이 한 값 의 합 은 전체 기이 한 값 의 합 의 99%이상 을 차지한다.즉,우 리 는 앞의 r 대 기이 한 값 으로 행렬 을 묘사 할 수 있다.r 는 m,n 보다 훨씬 작은 숫자 로 압축 행렬 을 진행 할 수 있다.
기이 한 값 분 해 를 통 해 우 리 는 더욱 적은 데 이 터 를 통 해 원 행렬 을 대체 하 는 것 과 비슷 할 수 있다.
기이 한 값 으로 svd 를 분해 하려 면 linalg.svd 를 다음 과 같이 직접 호출 할 수 있 습 니 다.

U, s, Vt = linalg.svd(img_gray)
그 중에서 U 는 m*m 매트릭스 이 고 Vt 는 n*n 매트릭스 입 니 다.
상기 이미지 에서 U 는(80,80)의 행렬 이 고 Vt 는(170,170)의 행렬 입 니 다.s 는 80 의 배열 로 s 는 img 의 기이 한 값 을 포함한다.
s 를 그림 으로 표시 하면 대부분의 기이 한 값 이 앞 부분 에 집중 되 어 있 는 것 을 볼 수 있 습 니 다.

이것 은 우리 가 s 의 앞부분 값 을 취하 여 이미지 의 재 구성 을 할 수 있다 는 것 을 의미한다.
s 를 사용 하여 그림 을 재 구성 하려 면 s 를 80*170 의 행렬 로 복원 해 야 합 니 다.

#   
import numpy as np
Sigma = np.zeros((80, 170))
for i in range(80):
    Sigma[i, i] = s[i]
U@Sigma@Vt 를 사용 하면 원래 의 행렬 을 재 구축 할 수 있 습 니 다.linalg.norm 을 계산 하여 원래 의 행렬 과 재 건 된 행렬 간 의 차 이 를 비교 할 수 있 습 니 다.

linalg.norm(img_gray - U @ Sigma @ Vt)
또는 np.allclose 를 사용 하여 두 행렬 의 차 이 를 비교 합 니 다.

np.allclose(img_gray, U @ Sigma @ Vt)
또는 s 배열 의 10 개 요소 만 취하 여 다시 그림 을 그리고 원 그림 과 의 차 이 를 비교 해 보 세 요.

k = 10
approx = U @ Sigma[:, :k] @ Vt[:k, :]
plt.imshow(approx, cmap="gray")
차이 가 크 지 않다 는 것 을 알 수 있다.

원본 그림 압축
지난 절 에 우 리 는 그 레이스 케 일 이미지 의 압축 을 어떻게 하 는 지 에 대해 이야기 했다.그러면 어떻게 원시 이미 지 를 압축 합 니까?
마찬가지 로 linalg.svd 를 사용 하여 행렬 을 분해 할 수 있 습 니 다.
하지만 사용 하기 전에 처리 가 필요 합 니 다.원본 이미지 의 imgarray 는 하나의(80,170,3)행렬 입 니 다.여기 서 투명 도 를 제거 하고 R,B,G 세 개의 속성 만 유지 합 니 다.
변환 을 진행 하기 전에 우 리 는 변환 할 필요 가 없 는 축 을 맨 앞 에 놓 아야 한다.즉,index=2 를 index=0 의 위치 로 바 꾼 다음 에 svd 작업 을 해 야 한다.

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)
마찬가지 로 현재 s 는(3,80)의 행렬 입 니까?1 차원 이 적 습 니까?그림 을 재 구축 하려 면 채 우 고 처리 해 야 합 니 다.마지막 으로 재 구축 한 그림 을 출력 해 야 합 니 다.

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)))

물론 앞의 K 개의 특징 값 을 선택 하여 그림 을 압축 할 수도 있 습 니 다.

approx_img = U @ Sigma[..., :k] @ Vt[..., :k, :]
print(approx_img.shape)
plt.imshow(np.transpose(approx_img, (1, 2, 0)))
재 구축 한 그림 은 다음 과 같 습 니 다.

대비 해 보면 일부 정밀도 가 손실 되 었 지만 이미 지 는 분별 할 수 있다.
총결산
이미지 의 변 화 는 많은 선형 연산 과 관련 될 것 이 므 로 여러분 은 이 글 을 예 로 들 어 자세히 연구 할 수 있 습 니 다.
NumPy 가 다 차원 배열 의 선형 대 수 를 실현 하 는 것 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 관련 NumPy 다 차원 배열 의 선형 대수 내용 은 우리 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 찾 아 보 세 요.앞으로 많은 응원 바 랍 니 다!

좋은 웹페이지 즐겨찾기