시내 이미지 해상도화 모니터
개요
이것은 Solafune에서 개최하는'시가지 초해상도화#MScup'경연의 기선이다.이 기사는 Public Score 0.790 정도의 기본선을 소개합니다.경기에 관한 상세한 상황은 홈페이지를 참조하시오.
초해상도 이미지 맵
⚠️
cf. @solafune(https://solafune.com)
コンテストの参加以外を目的とした利用及び商用利用は禁止されています。
商用利用・その他当コンテスト以外で利用したい場合はお問い合わせください。(https://solafune.com)
알고리즘 정보
이번에 사용된 알고리즘은 ESPCN 알고리즘입니다.이 알고리즘을 설명하기 위해서는 먼저 단일 이미지 초해상도에서 심층 학습을 이용하는 것을 간단하게 설명한다.
SRCNN
이 알고리즘은 이름과 같이 초해상도 작업에 CNN을 적용하는 알고리즘입니다.저해상도 이미지를 고해상도 이미지와 같은 크기로 조정해 3~5층 CNN을 통해 해상도를 높이는 알고리즘이다.
source: https://arxiv.org/pdf/1501.00092.pdf
FSRCNN
이 알고리즘은 상기 SRCNN 개발자가 고안한 것으로, SRCNN의 속도를 높이기 위해 개발됐다.SRCNN은 저해상도 이미지의 크기를 미리 조정했지만 이 부분은 속도의 병목이다.따라서 FSCNN에서는 크기를 먼저 조절하는 것이 아니라 네트워크의 마지막 층에서 디콘볼루션함으로써 해상도를 높인다.
source: https://arxiv.org/pdf/1608.00367.pdf
ESPCN
위의 FSCNN은 해상도를 높일 때 Deconvolution을 사용하지만 생성된 이미지를 보면 점박이 모양의 도안이 나타난다.이 문제를 개선하기 위해 ESPCN은 Deconvolution 대신 Sub-Pixel Convolution(Pixel Shuffle) 알고리즘을 사용합니다.
source: https://arxiv.org/pdf/1609.05158.pdf
이 Sub-Pixel Convolution은 향후 개발될 SRResnet 등의 알고리즘에 적용돼 향후 알고리즘 개발에 큰 영향을 미쳤다.
베이스라인
라이선스
게재된 프로그램은 Apache License 2.0입니다.
참고로 ESPCN도 아파치 라이센스 2.0에 공개됐다.
Copyright 2021 @Solafune
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
디렉토리 구조
┣━ train
┃ ┗━ train_*.tif
┣━ evaluation
┃ ┗━ evaluation_*.tif
┣━ output
┃ ┗━ test_*.tif
┗━ ESPCN_sample.py
개발 환경
FROM tensorflow/tensorflow:latest-gpu
RUN pip install Pillow
코드 설명
libraries
필요한 라이브러리 그룹을 Import로 만듭니다.
import os
os.environ["TF_FORCE_GPU_ALLOW_GROWTH"]= "true"
import tensorflow as tf
import tensorflow.keras.layers as kl
from tensorflow.python.keras import backend as K
import numpy as np
from PIL import Image
model
이번에 사용된 ESPCN의 모델을 정의합니다.
ESPCN에서는 픽셀 셔플을 사용해 샘플링을 진행하지만, 텐소플로우는 표준 탑재가 없어 자체 설치가 필요하다.
# ESPCN
class ESPCN(tf.keras.Model):
def __init__(self, input_shapes):
super().__init__()
self.input_shape_lm = ( None, input_shapes[0], input_shapes[1], 3)
self.upsampling_scale = 4
self.conv_0 = kl.Conv2D(64, 5, padding="same", activation="relu", input_shape=self.input_shape_lm)
self.conv_1 = kl.Conv2D(32, 3, padding="same", activation="relu")
self.pixel_shuffle = Pixel_shuffler(self.upsampling_scale, input_shapes)
def call(self, x):
conv2d_0 = self.conv_0(x)
conv2d_1 = self.conv_1(conv2d_0)
model = self.pixel_shuffle(conv2d_1)
return model
# Pixel Shuffle
class Pixel_shuffler(tf.keras.Model):
def __init__(self, upscale, input_shape):
super().__init__()
self.upscale = upscale
self.conv = kl.Conv2D(self.upscale**2 * 3, kernel_size=3, padding="same")
self.act = kl.Activation(tf.nn.relu)
# forward proc
def call(self, x):
d1 = self.conv(x)
d2 = self.act(tf.nn.depth_to_space(d1, self.upscale))
return d2
배우다
공부하는 부분이에요.
Optimzer는 Adam을, 손실 함수는 MSE를 사용합니다.
# 学習
class trainer(object):
def __init__(self, lr_shape, trained_model=""):
self.model = ESPCN ( lr_shape)
self.model.compile(optimizer=tf.keras.optimizers.Adam(),
loss=tf.keras.losses.MeanSquaredError(),
metrics=[self.ssim])
if trained_model != "":
self.model.load_weights(trained_model)
def train(self, lr_imgs, hr_imgs, out_path, batch_size, epochs):
cp_callback = tf.keras.callbacks.ModelCheckpoint(out_path,
save_weights_only=True,
verbose=10)
# 学習
his = self.model.fit(lr_imgs, hr_imgs, batch_size=batch_size, epochs=epochs, callbacks=[cp_callback])
print("___Training finished\n\n")
# パラメータ保存
print("___Saving parameter...")
self.model.save_weights(out_path)
print("___Successfully completed\n\n")
return his, self.model
# SSIM
def ssim(self, h3, hr_imgs):
return tf.image.ssim( h3, hr_imgs, max_val=1.0)
데이터 읽기
이미지 데이터를 불러옵니다.
읽는 데이터는 학습을 위해 정규화된 것이다.
또 데이터 증가로 교사 데이터로 상하좌우로 반전하는 이미지도 생성했다.
# Dataset creation
def create_dataset():
print("\n___Creating a dataset...")
prc = ['/', '-', '\\', '|']
cnt = 0
training_data =[]
for i in range(60):
d = "./train/"
# High-resolution image
img = Image.open(d+"train_{}_high.tif".format(i))
flip_img = np.array(ImageOps.flip(img))
mirror_img = np.array(ImageOps.mirror(img))
img = np.array(img)
img = (tf.convert_to_tensor(img, np.float32)) / 255.0
flip_img = (tf.convert_to_tensor(flip_img, np.float32)) / 255.0
mirror_img = (tf.convert_to_tensor( mirror_img, np.float32)) / 255.0
# Low-resolution image
low_img = Image.open(d+"train_{}_low.tif".format(i))
low_flip_img = np.array(ImageOps.flip(low_img))
low_mirror_img = np.array(ImageOps.mirror(low_img))
low_img = np.array( low_img)
low_img = (tf.convert_to_tensor( low_img, np.float32)) / 255.0
low_flip_img = (tf.convert_to_tensor( low_flip_img, np.float32)) / 255.0
low_mirror_img = (tf.convert_to_tensor( low_mirror_img, np.float32)) / 255.0
training_data.append([img,low_img])
training_data.append([flip_img,low_flip_img])
training_data.append([mirror_img,low_mirror_img])
cnt += 1
print("\rLoading a LR-images and HR-images...{} ({} / {})".format(prc[cnt%4], cnt, 60), end='')
print("\rLoading a LR-images and HR-images...Done ({} / {})".format(cnt, 60), end='')
print("\n___Successfully completed\n")
random.shuffle(training_data)
lr_imgs = []
hr_imgs = []
for hr, lr in training_data:
lr_imgs.append(lr)
hr_imgs.append(hr)
return np.array(lr_imgs), np.array(hr_imgs)
실행
위에서 정의한 함수류를 사용하여 실제 학습을 진행한다.
이번 배치 처리 건수는 15건, Epoc 건수는 1천400건이다.배치 수량의 경우 환경에 따라 변경됩니다.
# データセットの読み込み
lr_imgs, hr_imgs = create_dataset()
print("___Start training...")
Trainer = trainer(lr_imgs[0].shape)
his, model = Trainer.train(lr_imgs, hr_imgs, out_path="espcn_model_weight" , batch_size=15, epochs=1400)
추론
상술한 학습의 모형을 이용하여 추론을 진행하다.
추론에 사용되는 이미지는 데이터를 읽을 때와 마찬가지로 귀일화됩니다.
같은 추론 결과의 이미지도 귀일화되어 원시 이미지와 같은 형식으로 조정되었다.
for i in range(40):
d = "./evaluation/"
# Low-resolution image
img = np.array(Image.open(d+"test_{}_low.tif".format(i)))
img = (tf.convert_to_tensor( img, np.float32)) / 255.0
img = img[np.newaxis, :, :, :]
re = model.predict(img)
re = np.reshape(re, (1200, 1500, 3))
re = re * 255.0
re = np.clip(re, 0.0, 255.0)
sr_img = Image.fromarray(np.uint8(re))
sr_img.save("./output/test_{}_answer.tif".format(i))
print("Saved ./output/test_{}_answer.tif".format(i))
총결산
이번 베이스라인은 ESPCN 알고리즘을 사용해 초해상 기술을 시도했다.
환경에 따라 공부하는 데 몇 시간~1일 정도 걸렸다.
이번 대회에서 사용된 고해상도 이미지의 크기가 크고 네트워크를 구축할 때 비교적 큰 메모리가 필요한 알고리즘도 많아 시도할 수 없다.
또 손실 함수, 최적화 방법, 학습 계수 등 부분의 변경이 개선될 여지가 있을 수 있다.
반드시 이곳의 밑바닥을 참고하여 시합에 참가하세요.
참가는 이쪽에서 →"시가지 초해상도화#MScup"
Japan Solafune Developers Community
Solafune Global Developers Coomunity
Reference
이 문제에 관하여(시내 이미지 해상도화 모니터), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/ren_uechi/articles/ab9eea97ec42e5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)