tr_images ground_truths for i in range(batch—size) : tf. random—crop( cropped—image image, (input—size, input—size, channels)) tf. image. resize_images( ground—truth cropped_image, (output—size' output—size)) tf. image. resize_images( resized image cropped—image' (input—size / / scale' input—size / / scate) , method=tf. image. ResizeMeth0d. BICUBIC) tf. image. resize_images( tr—image resized image, (input—size, input—size) , method=tf. image. ResizeMethod . BICUBIC) ground—truths. append(ground—truth) tr—images ・ append(lr—image) tf. stack(lr—images, axis=@) lr_images tf. stack(ground—truths, axis=@) ground_truths return tr_images / 255 , ground—truths / 255 ランダムで切り出した 33px の画像 (cropped-image) を縮小して高解像度の画像 「 ground-truth 」とします。また、 cropped-image を縮小してから、もう一度拡大する ことで、画像を低解像度の画像「 tr-image 」を作成しています。 48 第 3 章超解像奮闘記
filename—queue = tf. train. string_input_producer(file tist, shuffte=True) tf. WhoteFileReader() reader value reader. read(filename_queue) tf. image. decode—jpeg(value, channels=channels) 1 mage lr_images ground_truths for i in range(batch—size) : tf. random—crop( cropped—image image, (input—size, input—size, channets)) lr_image = tf. image . resize—images( cropped—image' (input—size / / scate, input_size / / scate) , method=tf. image . ResizeMethod . BICUBIC) lr_image = tf. image . resize_images( lr_image, (input—size, input_size) , method=tf. image . ResizeMeth0d . BICUBIC) offset_teft (input_size ー output_size) / / 2 offset_top (input_size output—size) / / 2 ground—truth tf. image. crop—to—bounding—box( cropped—image, offset—top, offset—left, output—size, output_size) lr—images ・ append(lr—image) ground—truths . append(ground—truth) tf. stack(lr_images, axis=@) images tf. stack(ground—truths, axis=@) ground_truths return tr_images / 255 , ground_truths / 255 また、 evat. py でプロックに分割するときのスライド幅 (stride) を、 MODEL. INPUT_SIZE から MODEL. OUTPUT_SIZE に変更します ( リスト 3.6 ) 。 50 第 3 章超解像奮闘記
cropped—image, (output_size, output_size) ) resized_image = tf. image. resize_nmages( cropped—image, (input—size / / scale, input_size / / scate) , method=tf. image . ResizeMethod . BICUBIC) lr—image tf. image. resize_images( resized_image, (input—size, input_size) , method=tf. image. ResizeMethod . BICUBIC) ground—truths. append(ground_truth) lr—images ・ append(lr—image) lr_images tf. stack(lr_images, axis=@) ground_truths tf. stack(ground—truths, axis=@) return lr_images / 255 , ground_truths / 255 ます、読み込んだファイルを tf. image. decode ー jpeg でデコードします 次に、指定したサイズでランダムで切り抜き (tf. random_crop) 、画像 cropped_image を指定のサイズ (output_size) に縮小します。これが ground_truth 、モデルの出力とし て期待する高解像度の画像となります。 また、 cropped-image を元に、解像度の低い画像 (tr_image) を作ります。一度 scale に指定された大きさに縮小 (resize) したあと、再び拡大することで擬似的に解像度を下げ ☆☆☆ 1 1 x 1 1 33X33 cropped—image 図関数 load_image の動作 ます。 CNN 33X33 lr—image ground—truth 21X21 第 2 章 CNN で超解像 27
1 . 学習データの読み込み 2 . 誤差関数の定義 3 . 最適化アルゴリズムの設定 4 . 学習の実行 # coding: UTF-8 リスト 2.3 : srcnn/image 」 oader_svs. py 像度の画像 (ground-truths) の組み合わせです。 戻り値は、 batch ー size で指定した数の学習に使う低解像度の画像 (tr-images) と、高解 ズ (input-size) 、モデルが出力する画像サイズ (output-size) を指定します。 引数に読み込む画像ファイルのリスト (jpeg-file-list) と、モデルへ入力する画像サイ リスト 2.3 の関数 load ー image は、画像の読み込み処理です。 学習データの読み込み from from from future future_ future_ import absolute_import import division import print—function import tensorflow as tf def load_image(file—list, input—size' output—size' channets=l' scaIe=2, batch—size=l) : with tf. name_scope( 'image—loader—svs' ) : 26 tf. train. string—input—producer(fite—list, filename_queue shuffte=True) reader = tf. Wh01eFiteReader() reader. read(filename—queue) value tf. image ・ decode—jpeg(value, channets=channets) nmage lr_images ground_truths for i in range(batch—size) : cropped—image = tf. random—crop( image, (input—size, input—size' channets)) tf. image . resize_images( ground—truth 第 2 章 CNN で超解像
def __train(file_list, patches_count, train_dir) : checkpoint—path = OS . path . join(train—dir, 'model . ckpt') math . ceil(patches—count / FLAGS . batch_size) step—of—epoch toad—image ( images, ground—truths fite list, MODEL . INPUT_SIZE, MODEL . OUTPUT_SIZE, channeIs=MODEL . CHANNELS, scaIe=FLAGS. scale, batch_size=FLAGS . batch—size / / 4 ) FLAGS. min_after_dequeue + 4 ☆ FLAGS. batch_size capacity lr—image—batch, ground—truth-batch = tf. train . shuffte—batch( [images' ground—truths] , batch size=FLAGS . batch_size, capacity=capacity, enqueue_many=True, min_after_dequeue=FLAGS. min_after_dequeue, num_threads=FLAGS . num_threads) MODEL . inference(tr_image—batch) loss(sr—images, ground—truth-batch) sr_nmages IOSS tf.VariabIe(), trainable=FaIse) gtobal—step init_optimizer(FLAGS. learning—rate) opt opt. minimize(toss, global—step=global—step) train_op config = tf. ConfigProto( at10w_soft_pIacement=True, Iog—device—ptacement=FLAGS. tog—device—ptacement) saver = tf. train . Saver(tf. global—variables()) tf. train . Coordinator() coord with tf. Session(config=config) as sess: tf. train . get_checkpoint—state(train_dir) checkpoint if not (checkpoint and checkpoint. model—checkpoint—path) : sess . run(tf. global—variables—initializer()) else: 30 第 2 章 CNN で超解像
ムを検討するようにしてます。 リスト 2.5 : srcnn/train. py def __init_optimizer(learning_rate) : tf. train. AdamOptimizer(Iearning_rate) opt return opt 学習の実行 関数 __train は、これまで作成したプログラムを使ってモデルの学習を行います ( リスト 2.6 ) 。 load-image で学習データの画像を読み込み、 images と ground_truths を得ます 次に、 tf. trai n . shuffle_batch を通してミニバッチの数だけまとめた学習データを MODEL . inference に与えます。 得られる結果 (sr-images) が、超解像処理を施した画像です。 sr—images と ground—truth—batch の誤差を計算 (__toss して、 opt . minimize で 誤差が小さくなるようにパラメーターを更新します。 リスト 2.6 : srcnn/train. py tf. app . flags . FLAGS FLAGS tf. app . ftags . DEFINE—string('image_dir' tf. app . flags. DEFINE_integer('batch_size' None, " 学習画像のディレクトリ " ) 128 " ニバッチのサイズ " ) 0 . 001 , " 学習率 " ) tf. app. flags. DEFINE—float('learning_rate' tf. app. ftags. DEFINE_string('train_dir' . /train_sr' " 学習結果を保存するディレクトリ " ) tf. app. flags. DEFINE_integer('scate' 第 2 章 CNN で超解像 MODEL = m0de1915 # 使用するモデルを設定 tf. app . flags . DEFINE—integer('max_step' , ー 1 , " 学習する最大ステップ数 " ) 16 , " 処理するスレッド数 " ) tf. app . ftags. DEFINE_integer('num_threads' " dequeue をはじめるサンプル数 " ) 30000 , tf. app. flags. DEFINE—integer('min_after—dequeue' " op が実行されるデバイスを表示するかを選択 " ) Fatse, tf. app. flags. DEFINE—bootean( 'tog—device_placement' 29
tf. app. flags . FLAGS F LAGS tf. app . flags . DEFINE—string('hr_image—path' " 高解像度 ( 元画像 ) のパス " ) tf. app. flags . DEF 工 NE—string('Ir_image_path' tf. app. flags . DEFINE—string('sr_image_path' None, None, None, / 0 (psnr—bicubic, psnr—sr)) % .2fdb' print('PSNR(BICUBIC, (R): %. 2fdb hr—image, sr—image, dynamic—range=255) psnr_sr compare_psnr( hr image, lr—image, dynamic—range=255) psnr bicubic compare_psnr( ' サイズが異なる画像は評価できません ' sr_image. size) and lr_image. Size lr_image. size assert (hr_image. size sr_nmage imread(sr_file) lr image imread(lr_file) hr—image imread(hr_file) def compare(hr—file, tr—file, sr—file) : " 低解像度画像のパス " ) " 超解像画像のパス " ) 64 compare_ssim(hr_image, lr_image, win_size=3) ssim bicubic compare_ssim(hr_image, sr_image, wnn_size=3) S S 1 m S r def main(argv=None) : % (SSim bicubic, ssim_sr)) print('SSIM(BICUBIC, (R): % 4f % 4f assert OS . path. exists(FLAGS . sr—image—path) 96S IS not exist . , % FLAGS. tr_image_path assert OS . path . exists(FLAGS . tr—image—path) 96s is not exist. ' % FLAGS. hr image—path assert OS . path . exists(FLAGS. hr—image—path) FLAGS. sr_image—path 第 4 章さまざまなモデル FLAGS . sr_image_path) FLAGS . tr_image_path, compare(FLAGS . hr—image_path, 0 ′ 96S 1 S not exi St .
リスト 3.6 : srcnn/eval.py def _srcnn(image—path, scale, # スライド幅を変更 stride (MODEL. OUTPUT_SIZE, train_dir): MODEL. OUTPUT_SIZE) name, ext = OS. path. sptitext(os. path. basename(image_path)) dir OS . path . dirname(image_path) dir OS . path. join(dir, MODEL . NAME) if not os . path . exists(dir): os . mkdir(dir) padded_fite result fite OS . path . j Oi n ()i r , 96s—96dx ・ png % (name, scale)) OS . path . join(dir, '96s—96dx—resuIt ・ png % (name, scale)) lmage ・ open(image—path) 1 mage resized_image image . resize( (image. width 大 scale, image ・ height ☆ scale) , 工 mage. BICUBIC) if MODEL . CHANNELS resized image 1 : resized—image. convert('L') padding calc—padding(resized—image, stride) resized_image —pad(resized—image, padding=padding) —save—image(resized—image, padded—fite, padding=padding) blocks blocks extract_blocks(resized—image, stride) —process(btocks, train—dir) resutt_image result_image —reconstruct(blocks) _normalize(resutt_image) ☆ 255 # パディングの再計算 pad round ( (MODEL. INPUT_SIZE MODEL. OUTPUT_S 工 (E) / 2 ) padding[ 工 NDEX_PADDING_LEFT] pad padding[ 工 NDEX—PADDING_TOP] pad padding[INDEX_PADDING_RIGHT] + = pad padding[INDEX_PADDING_BOTTOM] + ニ pad —save—image(resutt—image, result—file, padding=padding) 第 3 章超解像奮闘記 51
OS . path . join(dir, MODEL. NAME) dir if not os . path . exists(dir) : os . mkdir(dir) OS . path . j 0i n ( di r , 96s—96dx ・ png OS . path . j Oi n ()i r , '96s-96dx—resuIt. png padded_fite % (name, scate)) resutt file % (name, scale)) lmage . open(image—path) 1 mage image. resize( resized_image (image. width ☆ scale, image . height ☆ scale) , lmage . BICUBIC) if MODEL . CHANNELS resized image resized_image . convert('L') calc—padding(resized—image, stride) padding —pad(resized—image, padding=padding) resized_image —save—image(resized—image, padded—file, padding=padding) extract_btocks(resized—image, stride) btocks —process(blocks, train—dir) btocks —reconstruct(btocks) resutt_image normalize(result_image) ☆ 255 result_image round((MODEL. INPUT_SIZE MODEL . OUTPUT_SIZE) / 2 ) pad pad padding[INDEX_PADDING_LEFT] pad paddingCINDEX_PADDING_TOP] padding[INDEX_PADDING_RIGHT] + = pad padding[INDEX_PADDING_BOTTOM] + = pad —save_image(result image, result—fite, padding=padding) file, padded—file return result 平価 一平価用の画像として、縦横 510PX5 の画像を用意しました ( 図 2.5 ) 。 三ロ 38 第 2 章 CNN で超解像
MODEL . inference(tr_image_batch, is_train=True, extra_ops=extra_ops) extra_ops sr_nmages IOSS loss(sr—images, ground—truth—batch) gtobal—step tf.VariabIe(), trainabIe=Fatse) init_optimizer(FLAGS . learning_rate) opt train—op opt. minimize(loss, globat_step=global—step) tf. group(train—op, *extra—ops) 図 4.13 は、表 4.5 の条件で学習した場合の誤差の変化です。 表 4.5 学習条件 条件 画像の倍率 (scale) 学習率 (learning-rate) ニバッチサイズ (batch_size) ステップ数 (max_step) チャンネル数 (CHANNELS) train—op 2 3 (RGB カラ 図 4.13 誤差の変イヒ (smoothing=O. 9) 6.88-3 5.3-7 ( 総 -3 町工 0 ま 3 3 ℃ 0 コチ 3 2. C00 チ 3 1 ℃ 0 ( 辱 3 C.a コ 28- 18. 0.80 4C00k 0 BatchNormalization がないモデルと比べると幾分、誤差のバラッキが小さくなっているよう です。 図 4.14 は、評価用の画像を 2 倍に拡大後、学習済みのモデルを使って超解像処理をした結果 第 4 章 さまざまなモデル 73