오늘 사용할 이미지는...
주말에 찍은 사진이다... ㅎㄷㄷ 소녀다리... 재성합니다...
일단 필요라이브러리 업로드!
import numpy as np
from sys import getsizeof
import os
import matplotlib.pyplot as plt
%matplotlib inline
그러면... 이미지를 불러오자!
posing_ori = plt.imread("data/image/posing_original.png")
posing_ori
대충 보면... 이미 정규화된 데이터같다!
확인해보면...
posing_ori.max(), posing_ori.min()
역시나 정규화가 되어있는데이터네...?
shape값을 한번 보면...
posing_ori.shape
채널 값이 4라서 RGB가 아닌 RGBA데이터 임을 알 수 있다!
한 번 R, G, B, A를 분리해보면...
R
plt.imshow(posing_ori[:, :, 0], cmap='Reds')
G
plt.imshow(posing_ori[:, :, 1], cmap='Greens')
B
plt.imshow(posing_ori[:, :, 2], cmap='Blues')
A
a는 투명도를 결정하는 것인데... cmap을 어떻게 설정하는지 모르겠다.
그래서 기본값인... 보랑, 노라가 나온다...
plt.imshow(posing_ori[:, :, 3])
이렇고...
합쳐서보면... 이렇고...
저장도 해준다!
plt.imshow(posing_ori)
plt.savefig('data/image/posing_ori')
이렇다...
넘파이의 linalg.svd를 사용하려 하는데...
채널이 4개여서...
계산 문제로...
전치행렬을 만들어주자!
posing_ori_transposed = np.transpose(posing_ori, (2, 0, 1))
posing_ori_transposed.shape
채널이 앞으로 빠졌다!
그럼 U, s Vt값을 만들어주자!
U, s, Vt = np.linalg.svd(posing_ori_transposed)
U.shape, s.shape, Vt.shape
이렇게 U, s, Vt가 만들어졌다!
복원하려면...
U, s, Vt를 곱해야하는데... s가 채널 각각의 shape은 (1,1051)이여서...
(1411, 1051)값으로 변경해 행렬을 만들어주자!
Sigma = np.zeros(posing_ori_transposed.shape)
for i in range(4):
np.fill_diagonal(Sigma[i, :, :], s[i, :])
채널 하나하나 Sigma의 값을 보면...
Sigma[0, :, :].shape, Sigma[1, :, :].shape, Sigma[2, :, :].shape, Sigma[3, :, :].shape
그럼...
복원해보면...
reconstructed = U @ Sigma @ Vt
reconstructed.shape
이렇게 원래대로 돌아왔다!
부동소수점 오류가 있나 확인해보자!
reconstructed.min(), reconstructed.max()
역시 오류가 생겼다!
그럼 clip을 사용해서 최대, 최소를, 0, 1로 하자!
reconstructed = np.clip(reconstructed, 0, 1)
reconstructed.min(), reconstructed.max()
그럼 원래 것과 비교를 해보자!
np.allclose로 비교해보면...
그럼 복원한 파일을 보자!
plt.imshow(np.transpose(reconstructed, (1, 2, 0)))
그럼 돌아가서...
R,G,B,A값의 s크기를... 보면...
plt.plot(np.linspace(0, 1051, 1051), s[0], color='red', marker='.')
plt.plot(np.linspace(0, 1051, 1051), s[1], color='green', marker='*')
plt.plot(np.linspace(0, 1051, 1051), s[2], color='blue', marker='x')
plt.plot(np.linspace(0, 1051, 1051), s[3], color='purple', marker='+')
겹쳐서 잘 안보이지만...
A값만 매우 살짝? 다르고... 추세가 거의 같다...
s에서 뒤로갈수록 숫자가 거의 0이다!
그러면 k=10으로 특이값 분해를 해보자!
분해를 한 뒤 저장까지 해준다!
k = 10
posing_10 = U @ Sigma[..., :k] @ Vt[:, :k, :]
posing_10 = np.clip(posing_10, 0, 1)
posing_10 = np.transpose(posing_10, (1, 2, 0))
plt.imshow(posing_10)
plt.savefig('data/image/posing_10.png')
화질.. ㅎㄷㄷ 하다!
이번엔 k=50으로 해보자!
k = 50
posing_50 = U @ Sigma[..., :k] @ Vt[:, :k, :]
posing_50 = np.clip(posing_50, 0, 1)
posing_50 = np.transpose(posing_50, (1, 2, 0))
plt.imshow(posing_50)
plt.savefig('data/image/posing_50.png')
화질이 좀 나아지긴 하지만 딱 모나리자 수준이다!
각각 파일의... 크기를 확인해보면...
print(format(os.stat("data/image/posing_10.png").st_size, ","))
print(format(os.stat("data/image/posing_50.png").st_size, ","))
print(format(os.stat("data/image/posing_ori.png").st_size, ","))
조금 차이가 있긴하지만...
그렇게 크지는? 않은 것 같다!
댓글