質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

87.33%

SegNet の画像サイズ変更方法

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,519

score 15

前提・実現したいこと

こちらのサイトに掲載されている SegNet プログラムについての質問です。
前回もSegNetに関する質問を投稿したのですが、そのときは画像データの学習(train.pyの実行)の際にエラーメッセージが出てしまう件についての解決策要求でした。
その件については、「GPUやメモリの性能不足である可能性があり、画像データのサイズを小さくしてはどうか」との助言をいただき、早速データセットフォルダ内の画像ファイルのサイズをすべて小さくし、それに合わせてプログラムコード中の該当する箇所をそのサイズ値に書き換えて実行しました。
その結果、train.py の実行時に以下のようなエラーが出てしまいました。

発生している問題・エラーメッセージ

runfile('C:/Users/t.k/.spyder-py3/train.py', wdir='C:/Users/t.k/.spyder-py3')
loading data...
.Traceback (most recent call last):

  File "<ipython-input-3-6de18f7107f1>", line 1, in <module>
    runfile('C:/Users/t.k/.spyder-py3/train.py', wdir='C:/Users/t.k/.spyder-py3')

  File "C:\Users\t.k\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 704, in runfile
    execfile(filename, namespace)

  File "C:\Users\t.k\Anaconda3\lib\site-packages\spyder_kernels\customize\spydercustomize.py", line 108, in execfile
    exec(compile(f.read(), filename, 'exec'), namespace)

  File "C:/Users/t.k/.spyder-py3/train.py", line 59, in <module>
    main()

  File "C:/Users/t.k/.spyder-py3/train.py", line 36, in main
    train_X, train_y = ds.load_data('train') # need to implement, y shape is (None, 360, 480, classes)

  File "C:\Users\t.k\.spyder-py3\dataset.py", line 60, in load_data
    label.append(self.one_hot_it(cv2.imread(os.getcwd() + txt[i][1][7:][:-1])[:,:,0]))

  File "C:\Users\t.k\.spyder-py3\dataset.py", line 43, in one_hot_it
    x[i,j,labels[i][j]] = 1

IndexError: index 12 is out of bounds for axis 2 with size 12

該当のソースコード

import cv2
import numpy as np

from keras.applications import imagenet_utils

import os

DataPath = './CamVid/'
data_shape = 176*240

class Dataset:
    def __init__(self, classes=12, train_file='train.txt', test_file='test.txt'):
        self.train_file = train_file
        self.test_file = test_file
        self.data_shape = 176*240
        self.classes = classes

    def normalized(self, rgb):
        #return rgb/255.0
        norm=np.zeros((rgb.shape[0], rgb.shape[1], 3),np.float32)

        b=rgb[:,:,0]
        g=rgb[:,:,1]
        r=rgb[:,:,2]

        norm[:,:,0]=cv2.equalizeHist(b)
        norm[:,:,1]=cv2.equalizeHist(g)
        norm[:,:,2]=cv2.equalizeHist(r)

        return norm

    def one_hot_it(self, labels):
        x = np.zeros([176,240,12])
        for i in range(176):
            for j in range(240):
                x[i,j,labels[i][j]] = 1
        return x

    def load_data(self, mode='train'):
        data = []
        label = []
        if (mode == 'train'):
            filename = self.train_file
        else:
            filename = self.test_file

        with open(DataPath + filename) as f:
            txt = f.readlines()
            txt = [line.split(' ') for line in txt]

        for i in range(len(txt)):
            data.append(self.normalized(cv2.imread(os.getcwd() + txt[i][0][7:])))
            label.append(self.one_hot_it(cv2.imread(os.getcwd() + txt[i][1][7:][:-1])[:,:,0]))
            print('.',end='')
        #print("train data file", os.getcwd() + txt[i][0][7:])
        #print("label data raw", cv2.imread(os.getcwd() + '/CamVid/trainannot/0001TP_006690.png'))
        return np.array(data), np.array(label)


    def preprocess_inputs(self, X):
    ### @ https://github.com/fchollet/keras/blob/master/keras/applications/imagenet_utils.py
        """Preprocesses a tensor encoding a batch of images.
        # Arguments
            x: input Numpy tensor, 4D.
            data_format: data format of the image tensor.
            mode: One of "caffe", "tf".
                - caffe: will convert the images from RGB to BGR,
                    then will zero-center each color channel with
                    respect to the ImageNet dataset,
                    without scaling.
                - tf: will scale pixels between -1 and 1,
                    sample-wise.
        # Returns
            Preprocessed tensor.
        """
        return imagenet_utils.preprocess_input(X)

    def reshape_labels(self, y):
        return np.reshape(y, (len(y), self.data_shape, self.classes))
from keras.layers import Input
from keras.layers.core import Activation, Flatten, Reshape
from keras.layers.convolutional import Convolution2D, Conv2D, MaxPooling2D, UpSampling2D
from keras.layers.normalization import BatchNormalization
from keras.models import Model
from keras.utils import np_utils

def SegNet(input_shape=(176, 240, 3), classes=12):
    ### @ https://github.com/alexgkendall/SegNet-Tutorial/blob/master/Example_Models/bayesian_segnet_camvid.prototxt
    img_input = Input(shape=input_shape)
    x = img_input
    # Encoder
    x = Conv2D(64, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    x = MaxPooling2D(pool_size=(2, 2))(x)

    x = Conv2D(128, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    x = MaxPooling2D(pool_size=(2, 2))(x)

    x = Conv2D(256, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)
    x = MaxPooling2D(pool_size=(2, 2))(x)

    x = Conv2D(512, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)

    # Decoder
    x = Conv2D(512, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)

    x = UpSampling2D(size=(2, 2))(x)
    x = Conv2D(256, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)

    x = UpSampling2D(size=(2, 2))(x)
    x = Conv2D(128, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)

    x = UpSampling2D(size=(2, 2))(x)
    x = Conv2D(64, (3, 3), padding="same")(x)
    x = BatchNormalization()(x)
    x = Activation("relu")(x)

    x = Conv2D(classes, (1, 1), padding="valid")(x)
    x = Reshape((input_shape[0] * input_shape[1], classes))(x)
    x = Activation("softmax")(x)
    model = Model(img_input, x)
    return model
import os
import glob
import numpy as np
import keras

from model import SegNet

import dataset

input_shape = (176, 240, 3)
classes = 12
epochs = 10
batch_size = 1
log_filepath='./logs/'

data_shape = 176*240

class_weighting = [0.2595, 0.1826, 4.5640, 0.1417, 0.5051, 0.3826, 9.6446, 1.8418, 6.6823, 6.2478, 3.0, 7.3614]

## set gpu usage
import tensorflow as tf
config = tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True, per_process_gpu_memory_fraction = 0.8))
session = tf.Session(config=config)
keras.backend.tensorflow_backend.set_session(session)

def main():
    print("loading data...")
    ds = dataset.Dataset(classes=classes)
    train_X, train_y = ds.load_data('train') # need to implement, y shape is (None, 360, 480, classes)

    train_X = ds.preprocess_inputs(train_X)
    train_Y = ds.reshape_labels(train_y)
    print("input data shape...", train_X.shape)
    print("input label shape...", train_Y.shape)

    test_X, test_y = ds.load_data('test') # need to implement, y shape is (None, 360, 480, classes)
    test_X = ds.preprocess_inputs(test_X)
    test_Y = ds.reshape_labels(test_y)

    tb_cb = keras.callbacks.TensorBoard(log_dir=log_filepath, histogram_freq=1, write_graph=True, write_images=True)
    print("creating model...")
    model = SegNet(input_shape=input_shape, classes=classes)
    model.compile(loss="categorical_crossentropy", optimizer='adadelta', metrics=["accuracy"])

    model.fit(train_X, train_Y, batch_size=batch_size, epochs=epochs,
              verbose=1, class_weight=class_weighting , validation_data=(test_X, test_Y), shuffle=True
              , callbacks=[tb_cb])

    model.save('seg.h5')

if __name__ == '__main__':
    main()

試したこと

元々のデータセットの画像サイズ (360×480) から(176×240)へ変更しました。
SegNetにおける画像サイズの変更については、ほかの質問者様が同様の質問を投稿されており、そこにあった解決方法に沿って実行してみましたが無理でした。
(「FastStone Photo Resizer」で色深度8bit(256)まで指定して(176×240)に画像サイズを変更)

testannot
testannot 

trainannot
trainannot

valannot
valannot

補足情報(FW/ツールのバージョンなど)

開発環境

  • Windows7 (64bit)
  • Spyder (Python 3.6)
  • Keras 2.2.4
  • Tensorflow 1.12.0

CPU : Intel(R) Core(TM) i7    970 @ 3.20GHz
メモリ(RAM) : 16.0 GB
GPU : NVIDIA GeForce GTX 570

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 2

checkベストアンサー

0

アップしていただいた画像を下記のコードで確認したところ

import cv2
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

pil_img = Image.open("./CamVid/trainannot-test.png")  # PIL で読み込む。アップいただいた画像
img = np.asarray(pil_img)  # numpy 配列に変換する。

print(img.shape)  # (176, 240)
print(img)


class Label:
    Sky = 0
    Building = 1
    Pole = 2
    Road = 3
    Pavement = 4
    Tree = 5
    SignSymbol = 6
    Fence = 7
    Car = 8
    Pedestrian = 9
    Bicyclist = 10
    Unlabelled = 11

plt.imshow(np.where(img == 3, 100, 0)) # == の後の数字を変えるとその領域が表示される Road=3
plt.axis('off')
plt.show()

例えば img == 0 としてskyを表示させるとsky以外の部分もラベルがついているように
思えますので、この辺りが原因ではないかと思われます。
「FastStone Photo Resizer」で画像サイズを変換する際に「Advanced Options」で
「Resize」は「In Pixels」で(240×176)で「Filter」は「<None>」を選択し、
「Color Depth」は「256(8bit)」で変換してもダメでしょうか。
上記設定で変換するとファイルサイズが2kB前後になりうまく動作しました(アップいただいた
画像は約4kBでした)。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/26 16:32

    ご返信ありがとうございます。
    「Advanced Options」で何かのフィルタを設定していたみたいなので、フィルタをはずして再度リサイズしたところ、無事プログラムが動きました。ようやく次に進めそうです。
    SegNetに関しては、今後また疑問や問題は出てくるかと思いますが、ひとまずこの件は解決とさせていただきます。本当にありがとうございました。

    キャンセル

0

私も初心者ですのでお力になれるかどうかわかりませんが、上記の「FastStone Photo Resizer」の
解決方法を投稿しております。やはり画像に問題があるのではないかと思いますが、
一度testannot,trainannot,valannotフォルダ内の変換した画像の一つをアップ(挿入)いただけ
ませんでしょうか。確認してみたいと思います。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/26 14:41

    ご回答くださりありがとうございます。SegNet関連の質問で、自分がつまずいている内容と同じ質問をされているのを見かけ、hss_様の投稿された解決方法を試させていただきました。
    しかし、記載された手法どうりに行ってもうまくいかず、このような質問をさせていただいた次第です。
    ご指示のとおり、testannot, trainannot, valannotフォルダ内画像の1枚をそれぞれアップしました。
    大変恐縮ですが、確認のほうをぜひよろしくお願いいたします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 87.33%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る