내용

글번호 797
작성자 허진경
작성일 2018-01-19 12:14:46
제목 SVD를 이용한 영상 압축
내용 SVD를 이용한 영상 압축 코드와 결과
> #현재 작업 디렉토리를 변경합니다.
> setwd("C:/R-workplace")
> 
> #MNIST 학습 이미지 데이터를 불러옵니다.
> to.read <- file("./Data/MNIST/train-images.idx3-ubyte", "rb")
> 
> #헤더 정보를 읽어들입니다. 이 값은 이미지가 아니기 때문에 버려야 합니다.
> readBin(to.read, integer(), n=4, endian="big")  # skip header 2051 60000    28    28
[1]  2051 60000    28    28
> 
> #이미지 영역을 2x2로 나눕니다. 
> # 그리고 그래프의 여백을 모두 0.5로 설정합니다. x,y 축을 표시하지 않습니다.
> op <- par(mfrow=c(2,2), mar=c(0.5,0.5,1.5,0.5), yaxt="n", xaxt="n")
> 
> #헤더를 제외한 처음 784픽셀을 읽어 matrix로 만듭니다.
> m <- matrix(readBin(to.read, integer(), n=28*28, size=1, signed=F), 28, 28);
> 
> #matrix를 이용해 이미지를 표현합니다.
> image(m[, 28:1], main="Original")
> 
> #특이값 분석을 수행합니다.
> msvd <- svd(m)
> 
> #U, Sigma, V를 분리합니다.
> U <- msvd$u
> S <- diag(msvd$d) # 특이값을 이용해 대각선이 mavd$d인 대각행렬을 생성합니다.
> V <- msvd$v
> 
> #특이값 분해 공식에 의해 U, S, V를 이용해 원본 이미지를 계산해 냅니다.
> m2 <- U %*% S %*% t(V) 
> 
> #특이갑 분해 공식에 의해 만들어진 이미지를 출력합니다.
> image(m2[,28:1], main="SVD")
> 
> #thin,compacted, truncated = reduced
> # 특이값을 축소합니다. 특이값 28개 중에서 8개만 사용합니다.
> RU <- U[, 1:8]
> RS <- S[1:8, 1:8]
> RV <- V[, 1:8]
> 
> #특이값 축소한 행렬을 이용해 원본 이미지를 추측합니다.
> m3 <- RU %*% RS %*% t(RV)
> image(m3[,28:1], main="Truncated SVD - 8")
> 
> length(m) # 원본 이미지를 저장하기 위한 행렬의 크기입니다.
[1] 784
> length(RU) + NROW(msvd$d[1:8]) + length(RV) # 특이갑 분해후 축소한 행렬의 크기입니다.
[1] 456
> 
> #더 축소해 봅니다.
> RU <- U[, 1:5]
> RS <- S[1:5, 1:5]
> RV <- V[, 1:5]
> 
> m4 <- RU %*% RS %*% t(RV)
> image(m4[,28:1], main="Truncated SVD - 5")
> 
> length(RU) + NROW(msvd$d[1:5]) + length(RV)
[1] 285
> 
> #파라미터를 원래대로 되돌립니다.
> par(op)
> 
이미지 코드
#현재 작업 디렉토리를 변경합니다.
setwd("C:/R-workplace")

#MNIST 학습 이미지 데이터를 불러옵니다.
to.read <- file("./Data/MNIST/train-images.idx3-ubyte", "rb")

#헤더 정보를 읽어들입니다. 이 값은 이미지가 아니기 때문에 버려야 합니다.
readBin(to.read, integer(), n=4, endian="big")  # skip header 2051 60000    28    28

#이미지 영역을 2x2로 나눕니다. 
# 그리고 그래프의 여백을 모두 0.5로 설정합니다. x,y 축을 표시하지 않습니다.
op <- par(mfrow=c(2,2), mar=c(0.5,0.5,1.5,0.5), yaxt="n", xaxt="n")

#헤더를 제외한 처음 784픽셀을 읽어 matrix로 만듭니다.
m <- matrix(readBin(to.read, integer(), n=28*28, size=1, signed=F), 28, 28);

#matrix를 이용해 이미지를 표현합니다.
image(m[, 28:1], main="Original")

#특이값 분석을 수행합니다.
msvd <- svd(m)

#U, Sigma, V를 분리합니다.
U <- msvd$u
S <- diag(msvd$d) # 특이값을 이용해 대각선이 mavd$d인 대각행렬을 생성합니다.
V <- msvd$v

#특이값 분해 공식에 의해 U, S, V를 이용해 원본 이미지를 계산해 냅니다.
m2 <- U %*% S %*% t(V) 

#특이갑 분해 공식에 의해 만들어진 이미지를 출력합니다.
image(m2[,28:1], main="SVD")

#thin,compacted, truncated = reduced
# 특이값을 축소합니다. 특이값 28개 중에서 8개만 사용합니다.
RU <- U[, 1:8]
RS <- S[1:8, 1:8]
RV <- V[, 1:8]

#특이값 축소한 행렬을 이용해 원본 이미지를 추측합니다.
m3 <- RU %*% RS %*% t(RV)
image(m3[,28:1], main="Truncated SVD - 8")

length(m) # 원본 이미지를 저장하기 위한 행렬의 크기입니다.
length(RU) + NROW(msvd$d[1:8]) + length(RV) # 특이갑 분해후 축소한 행렬의 크기입니다.

#더 축소해 봅니다.
RU <- U[, 1:5]
RS <- S[1:5, 1:5]
RV <- V[, 1:5]

m4 <- RU %*% RS %*% t(RV)
image(m4[,28:1], main="Truncated SVD - 5")

length(RU) + NROW(msvd$d[1:5]) + length(RV)

#파라미터를 원래대로 되돌립니다.
par(op)