« カメラ付きのワインセラー”Plum wine system” | トップページ | Lenovo G580が我が家にやってきた »

2018年1月13日 (土)

TensorFlow+KerasでSSDを独自データで使えるようにしてみた

物体検出コードといえば以前「ディープラーニングで一般物体検出する手法”YOLO”のTensorFlow版で独自データセットを使えるようにしてみた: EeePCの軌跡」という記事で紹介したYOLOv1という手法を使えるようにしたのですが、このYOLOv1、精度はいまいち。

ということで、最新のSSD or YOLOv2を使えるようにしたいなぁと考え、何とかこのSSD(Single Shot MultiBox Detector)を使えるようにしました。

コードの入手先はこちら。

GitHub - ryokov8/ssd_keras

参考サイトはこちら。

物体検出アルゴリズム(SSD : Single Shot MultiBox Detector)を学習させてみる - Qiita

準備

まず、このコードは”Keras”というのを使います。

実はこいつが曲者で、最新のKeras(バージョンが2.0以降)を入れると動きません。バージョンは”1.2.2”を入れる必要があります。

> pip install --upgrade keras==1.2.2

とすれば、Windows版Anacondaでもインストールできました。

TensorFlowは1.0以降であればOKのようです。我が家は1.2ですが、動きました。

ただ、環境によってはバックエンドがTensorFlowではない場合があります。その場合は以下を参考にバックエンドをTensorFlowに変更しておいてください。

Keras バックエンドの変更 - Qiita

先のGitHubリンクからコードをゲットします。

Windowsの場合は「GitHub - ryokov8/ssd_keras」をクリックして、その中の「Clone or Download」をクリック、「Download ZIP」をクリックしてZIP形式のファイルを落します。

解凍したのち、そのフォルダ内に「checkpoints」という空フォルダを作っておいてください。

Linuxだと、下記のコマンドで一発ですね。

> git clone https://github.com/rykov8/ssd_keras

さて、とりあえず動かすために、Pascal VOCのデータをダウンロードします。

私はVOC2007を使いました。入手の仕方は「The PASCAL Visual Object Classes Challenge 2007 (VOC2007)」のサイトの中ほどにある「Development Kit」の「 training/validation data 」をクリックします。

これを解凍すると、「VOCdevkit」というフォルダができます。これを、上のSSDのコードのあるところ(ssd_keras-master)にそのまま入れます。

他には学習済みデータを入手する必要があります。

https://mega.nz/#F!7RowVLCL!q3cEVRK9jyOSB9el3SssIA」から「weights_SSD300.hdf5」をダウンロードしてください。右クリックして「ダウンロード」-「標準ダウンロード」で入手できます。これもSSDコードのフォルダ(ssd_keras-master)に入れます。

他に、以下のコードを作っておいてください。参考サイトからほぼそのままいただきました。ファイル名は「train_ssd_keras.py」とでもしておいてください。

import cv2
import keras
from keras.applications.imagenet_utils import preprocess_input
from keras.backend.tensorflow_backend import set_session
from keras.models import Model
from keras.preprocessing import image
import matplotlib.pyplot as plt
import numpy as np
import pickle
from random import shuffle
from scipy.misc import imread
from scipy.misc import imresize
import tensorflow as tf

from ssd import SSD300
from ssd_training import MultiboxLoss
from ssd_utils import BBoxUtility

plt.rcParams['figure.figsize'] = (8, 8)
plt.rcParams['image.interpolation'] = 'nearest'

np.set_printoptions(suppress=True)

# 21
NUM_CLASSES = 21 #4
input_shape = (300, 300, 3)

priors = pickle.load(open('prior_boxes_ssd300.pkl', 'rb'))
bbox_util = BBoxUtility(NUM_CLASSES, priors)

# gt = pickle.load(open('gt_pascal.pkl', 'rb'))
gt = pickle.load(open('VOC2007.pkl', 'rb'))
keys = sorted(gt.keys())
num_train = int(round(0.8 * len(keys)))
train_keys = keys[:num_train]
val_keys = keys[num_train:]
num_val = len(val_keys)

class Generator(object):
    def __init__(self, gt, bbox_util,
                 batch_size, path_prefix,
                 train_keys, val_keys, image_size,
                 saturation_var=0.5,
                 brightness_var=0.5,
                 contrast_var=0.5,
                 lighting_std=0.5,
                 hflip_prob=0.5,
                 vflip_prob=0.5,
                 do_crop=True,
                 crop_area_range=[0.75, 1.0],
                 aspect_ratio_range=[3./4., 4./3.]):
        self.gt = gt
        self.bbox_util = bbox_util
        self.batch_size = batch_size
        self.path_prefix = path_prefix
        self.train_keys = train_keys
        self.val_keys = val_keys
        self.train_batches = len(train_keys)
        self.val_batches = len(val_keys)
        self.image_size = image_size
        self.color_jitter = []
        if saturation_var:
            self.saturation_var = saturation_var
            self.color_jitter.append(self.saturation)
        if brightness_var:
            self.brightness_var = brightness_var
            self.color_jitter.append(self.brightness)
        if contrast_var:
            self.contrast_var = contrast_var
            self.color_jitter.append(self.contrast)
        self.lighting_std = lighting_std
        self.hflip_prob = hflip_prob
        self.vflip_prob = vflip_prob
        self.do_crop = do_crop
        self.crop_area_range = crop_area_range
        self.aspect_ratio_range = aspect_ratio_range

    def grayscale(self, rgb):
        return rgb.dot([0.299, 0.587, 0.114])

    def saturation(self, rgb):
        gs = self.grayscale(rgb)
        alpha = 2 * np.random.random() * self.saturation_var
        alpha += 1 - self.saturation_var
        rgb = rgb * alpha + (1 - alpha) * gs[:, :, None]
        return np.clip(rgb, 0, 255)

    def brightness(self, rgb):
        alpha = 2 * np.random.random() * self.brightness_var
        alpha += 1 - self.saturation_var
        rgb = rgb * alpha
        return np.clip(rgb, 0, 255)

    def contrast(self, rgb):
        gs = self.grayscale(rgb).mean() * np.ones_like(rgb)
        alpha = 2 * np.random.random() * self.contrast_var
        alpha += 1 - self.contrast_var
        rgb = rgb * alpha + (1 - alpha) * gs
        return np.clip(rgb, 0, 255)

    def lighting(self, img):
        cov = np.cov(img.reshape(-1, 3) / 255.0, rowvar=False)
        eigval, eigvec = np.linalg.eigh(cov)
        noise = np.random.randn(3) * self.lighting_std
        noise = eigvec.dot(eigval * noise) * 255
        img += noise
        return np.clip(img, 0, 255)

    def horizontal_flip(self, img, y):
        if np.random.random() < self.hflip_prob:
            img = img[:, ::-1]
            y[:, [0, 2]] = 1 - y[:, [2, 0]]
        return img, y

    def vertical_flip(self, img, y):
        if np.random.random() < self.vflip_prob:
            img = img[::-1]
            y[:, [1, 3]] = 1 - y[:, [3, 1]]
        return img, y

    def random_sized_crop(self, img, targets):
        img_w = img.shape[1]
        img_h = img.shape[0]
        img_area = img_w * img_h
        random_scale = np.random.random()
        random_scale *= (self.crop_area_range[1] -
                         self.crop_area_range[0])
        random_scale += self.crop_area_range[0]
        target_area = random_scale * img_area
        random_ratio = np.random.random()
        random_ratio *= (self.aspect_ratio_range[1] -
                         self.aspect_ratio_range[0])
        random_ratio += self.aspect_ratio_range[0]
        w = np.round(np.sqrt(target_area * random_ratio))
          h = np.round(np.sqrt(target_area / random_ratio))
        if np.random.random() < 0.5:
            w, h = h, w
        w = min(w, img_w)
        w_rel = w / img_w
        w = int(w)
        h = min(h, img_h)
        h_rel = h / img_h
        h = int(h)
        x = np.random.random() * (img_w - w)
        x_rel = x / img_w
        x = int(x)
        y = np.random.random() * (img_h - h)
        y_rel = y / img_h
        y = int(y)
        img = img[y:y+h, x:x+w]
        new_targets = []
        for box in targets:
            cx = 0.5 * (box[0] + box[2])
            cy = 0.5 * (box[1] + box[3])
            if (x_rel < cx < x_rel + w_rel and
                y_rel < cy < y_rel + h_rel):
                xmin = (box[0] - x_rel) / w_rel
                ymin = (box[1] - y_rel) / h_rel
                xmax = (box[2] - x_rel) / w_rel
                ymax = (box[3] - y_rel) / h_rel
                xmin = max(0, xmin)
                ymin = max(0, ymin)
                xmax = min(1, xmax)
                ymax = min(1, ymax)
                box[:4] = [xmin, ymin, xmax, ymax]
                new_targets.append(box)
        new_targets = np.asarray(new_targets).reshape(-1, targets.shape[1])
        return img, new_targets

    def generate(self, train=True):
        while True:
            if train:
                shuffle(self.train_keys)
                keys = self.train_keys
            else:
                shuffle(self.val_keys)
                keys = self.val_keys
            inputs = []
            targets = []
            for key in keys:
                img_path = self.path_prefix + key
                img = imread(img_path).astype('float32')
                y = self.gt[key].copy()
                if train and self.do_crop:
                    img, y = self.random_sized_crop(img, y)
                img = imresize(img, self.image_size).astype('float32')

                if train:
                    shuffle(self.color_jitter)
                    for jitter in self.color_jitter:
                        img = jitter(img)
                    if self.lighting_std:
                        img = self.lighting(img)
                    if self.hflip_prob > 0:
                        img, y = self.horizontal_flip(img, y)
                    if self.vflip_prob > 0:
                        img, y = self.vertical_flip(img, y)
                #
                #print(y)
                y = self.bbox_util.assign_boxes(y)
                #print(y)
                inputs.append(img)
                        targets.append(y)
                if len(targets) == self.batch_size:
                    tmp_inp = np.array(inputs)
                    tmp_targets = np.array(targets)
                    inputs = []
                    targets = []
                    yield preprocess_input(tmp_inp), tmp_targets

path_prefix = './VOCdevkit/VOC2007/JPEGImages/'
gen = Generator(gt, bbox_util, 4, path_prefix,
                train_keys, val_keys,
                (input_shape[0], input_shape[1]), do_crop=False)

model = SSD300(input_shape, num_classes=NUM_CLASSES)
model.load_weights('weights_SSD300.hdf5', by_name=True)

freeze = ['input_1', 'conv1_1', 'conv1_2', 'pool1',
          'conv2_1', 'conv2_2', 'pool2',
          'conv3_1', 'conv3_2', 'conv3_3', 'pool3']#,
#           'conv4_1', 'conv4_2', 'conv4_3', 'pool4']

for L in model.layers:
    if L.name in freeze:
        L.trainable = False

def schedule(epoch, decay=0.9):
    return base_lr * decay**(epoch)

callbacks = [keras.callbacks.ModelCheckpoint('./checkpoints/weights.{epoch:02d}-{val_loss:.2f}.hdf5',
                                             verbose=1,
                                             save_weights_only=True),
             keras.callbacks.LearningRateScheduler(schedule)]

base_lr = 3e-4
optim = keras.optimizers.Adam(lr=base_lr)
model.compile(optimizer=optim,
              loss=MultiboxLoss(NUM_CLASSES, neg_pos_ratio=2.0).compute_loss)

nb_epoch = 100
history = model.fit_generator(gen.generate(True), gen.train_batches,
                              nb_epoch, verbose=1,
                              callbacks=callbacks,
                              validation_data=gen.generate(False),
                              nb_val_samples=gen.val_batches,
                              nb_worker=1)

inputs = []
images = []
img_path = path_prefix + sorted(val_keys)[0]
img = image.load_img(img_path, target_size=(300, 300))
img = image.img_to_array(img)
images.append(imread(img_path))
inputs.append(img.copy())
inputs = preprocess_input(np.array(inputs))

preds = model.predict(inputs, batch_size=1, verbose=1)
results = bbox_util.detection_out(preds)

for i, img in enumerate(images):
    # Parse the outputs.
    det_label = results[i][:, 0]
    det_conf = results[i][:, 1]
    det_xmin = results[i][:, 2]
    det_ymin = results[i][:, 3]
    det_xmax = results[i][:, 4]
    det_ymax = results[i][:, 5]

    # Get detections with confidence higher than 0.6.
    top_indices = [i for i, conf in enumerate(det_conf) if conf >= 0.6]

    top_conf = det_conf[top_indices]
    top_label_indices = det_label[top_indices].tolist()
    top_xmin = det_xmin[top_indices]
    top_ymin = det_ymin[top_indices]
    top_xmax = det_xmax[top_indices]
    top_ymax = det_ymax[top_indices]

    colors = plt.cm.hsv(np.linspace(0, 1, NUM_CLASSES)).tolist()

    plt.imshow(img / 255.)
    currentAxis = plt.gca()

    for i in range(top_conf.shape[0]):
        xmin = int(round(top_xmin[i] * img.shape[1]))
        ymin = int(round(top_ymin[i] * img.shape[0]))
        xmax = int(round(top_xmax[i] * img.shape[1]))
        ymax = int(round(top_ymax[i] * img.shape[0]))
        score = top_conf[i]
        label = int(top_label_indices[i])
        # label_name = voc_classes[label - 1]
        display_txt = '{:0.2f}, {}'.format(score, label)
        coords = (xmin, ymin), xmax-xmin+1, ymax-ymin+1
        color = colors[label]
        currentAxis.add_patch(plt.Rectangle(*coords, fill=False, edgecolor=color, linewidth=2))
        currentAxis.text(xmin, ymin, display_txt, bbox={'facecolor':color, 'alpha':0.5})

    plt.show()

コードのあるフォルダ(ssd_keras-master)の中にある「testing_utils」の中の「videotest.py」というコードは、一部修正が必要です。

87、88行目にある以下のコードを

        vidw = vid.get(cv2.cv.CV_CAP_PROP_FRAME_WIDTH)
        vidh = vid.get(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT)

以下のように変えます。

        vidw = vid.get(cv2.CAP_PROP_FRAME_WIDTH)
        vidh = vid.get(cv2.CAP_PROP_FRAME_HEIGHT)

これで、準備完了です。

学習

まず最初に「PASCAL_VOC」というフォルダに「get_data_from_XML.py」というコードがあるはずです。これを一つ上のフォルダ(ssd_keras-master)に移動し、実行します。

> python get_data_from_XML.py

すると「VOC2007.pkl」というファイルができるはずです。

これができたら、いよいよ実行です。

> python train_ssd_keras.py

これで「VOC2007」のデータを使って、学習がはじまるはずです。

100 epochs実行するのに、うちの環境(Corei3 3220 3.3GHz + GeForce 1050Ti 4GB)では約12時間かかりました。

終わると、「checkpoints」というフォルダに学習済みデータが入っているはずです(10 epochs毎)。

これを使って、いよいよ動画の”物体検出”を実行します。

検出(動画)

ここでは、動画を使ったリアルタイム検出を行います。

まず「testing_utils」というフォルダに、物体検出させたい動画を入れます(ホームビデオなど)。

続いて、「videotest_example.py」を開きます。18行目の「model.load_weights('~')」の' '内に学習済みデータのファイル名(ex. ../checkpoints/weights.96-2.83.hdf5)を入れて、24行目の「vid_test.run('~')」の' '内には動画ファイル名を入れます。

以下のような画像が出てくるはずです。

Ssdtest01

うちの環境では、7FPS程度しか出ません。

不思議と元データ「weights_SSD300.hdf5」を使うと、13FPS出るんですけどね。学習データによって倍もフレームレートが変わるという理由がよくわかりませんね。

ともかく、精度はまあまあありそうです。

独自データでの学習

さて、これまVOC2007のデータを使った話。独自データを使うにはどうするのか?

まずは、独自データとなる画像を集めます。これは必須。

続いて、「AnnotationTool.exe」をダウンロードします。

私がとりあえず作った、Windows上で動かすアノテーションデータ作成ソフトです。

使い方は以下。

-----------------------------------------------------------------------

Annotation00

① まずアノテーションファイル(*.xmlと”trainval.txt”)を保存するフォルダ(作業フォルダ)を作りドラッグ&ドロップ

② アノテーションを作成したい画像ファイルをドラッグ&ドロップ

③ 画像ファイルが出てくるので、物体をマウスで囲みます

④ ”ラベル名”のテキストボックスに物体の名前を書きます(半角英数) 

⑤ ”ラベル作成”をクリックすると登録

同一画像内で認識させたい物体の数だけ③~⑤を繰り返します。

⑥ 一通り終わったら「Annotation追加」をクリック

次の画像ファイルを読み込むため、再び②で別の画像を読み込み、⑥までを繰り返します。

すべての画像ファイルのアノテーション登録が終わったら

⑦ ”終了”をクリック

-----------------------------------------------------------------------

これを実行すると、画像ファイル分の「~.xml」ファイルと、「trainval.txt」ができているはずです。

これを、以下のように「VOCdevkit/VOC2007」に反映。

・ 「Annotations」フォルダには作成されたxmlファイルを全部入れます

・ 「ImageSets/Main」にある「trainval.txt」に、上で作られた「trainval.txt」の中身を追記します。

・ 「JPEGImages」フォルダに、独自データの画像ファイルをすべて入れます

そのあと、「get_data_from_XML.py」の中身を書き換えます。

42行目「if name == 'aeroplane':」以降に並んだ20個のラベルを、独自データ分のラベルと置き換えます。

例えば「イノシシ」と「鹿」と「馬」の画像ファイルを加えて、それぞれラベルを「inoshishi」、「shika」、「uma」としたいとします。その場合、42行目以降のコードは

        if name == 'inoshishi':
            one_hot_vector[0] = 1
        elif name == 'shika':
            one_hot_vector[1] = 1
        elif name == 'uma':
            one_hot_vector[2] = 1
         elif name == 'boat':
            one_hot_vector[3] = 1
        elif name == 'bottle':
         ・
         ・
         ・

となります(赤の部分が変更部位)。 ('uma'は'horse'じゃないのか等のツッコミはなしでお願いします)

この状態で

> python get_data_from_XML.py

を実行。

独自データ版の「VOC2007.pkl」ができるはずです。

この状態で、上の「学習」手順に基づき、学習コード(train_ssd_keras.py)を実行。

動画から物体検出させる場合は「testing_utils」の「videotest_example.py」の12行目を、上と同じラベルに書き換えます。あとは「検出(動画)」手順そのまま。

これで、独自データの検出が可能になるはず・・・です。

実は私自身、これを書いている時点ではまだ実行していないのですが、VOC2007のデータを使った学習ができているので、多分可能なはずです。

こちらのサイトでは、実際に動作に成功しているようです。

物体検出用SSD_Kerasで使える学習モデルの作成方法 | AI coordinator

とりあえず、これでSSDを実装することができました。

あとはネットワークを深層化したりしてやれれば万々歳なのですが、まだそこまでは試しておりません。

あと、どういうわけかこのコード、会社では同じようにやっても動かないんですよね。Keras 1.2.2にダウングレードしたのに、Keras 2.0.6で動かしたときのエラーが出ます。理由は不明。

Kerasというのはコードが書きやすくなる半面、学習データがブラックボックス化されるというか、どういう形式で書きこんでいるのかがわからなくなりますね。さらに、1.xから2.0に変えた時の変化点が大きすぎです。おかげで、Kerasのことはあまり好きになれません。

とはいえ、手軽に使える便利なコードなので、このSSD_Keras、おすすめです。

初めてのTensorFlow 数式なしのディープラーニング

« カメラ付きのワインセラー”Plum wine system” | トップページ | Lenovo G580が我が家にやってきた »

数値解析系」カテゴリの記事

コメント

過去記事への投稿失礼します。

非常にためになる記事をありがとうございます。
一通り動いたのですが、気づいたことがあるのでご連絡させていただきます。

独自データでのget_data_from_XML.py実行時にエラーになったので調べてみたところ、
AnnotationTool.exeを実行してできる .xml ファイルの3行目がとなっていますが、
の誤りではないでしょうか?(全て置換したところうまく動きました)
ご確認いただけたらと思いますし、可能であれば修正版をリリースいただけると、
非常に助かるので、ご検討いただければ幸いです。

こんにちは、機会学習勉強中さん。

ご指摘ありがとうございます。ただ、今ちょうど出先でして、なんとか今夜中に対応したいと思います。それまでお待ちいただけますか?

ご連絡いただきありがとうございます。
また、ご対応いただけるとのことで、大変ありがとうございます!
昨日のコメント内で肝心な部分が消えていたので、今更ですが念のため改めて書かせていただきます。
3行目のspirceとなっている箇所ですが、正しくはsourceかと思いますので、ご確認いただければ幸いです。

こんにちは、機械学習勉強中 さん。

たった今、アップいたしました。おっしゃる通り、”source”が”spirce”になってますね。ソースを直し、修正できていることを確認いたしました。

世の中にあるAnnotationツールに比べると、ずいぶんと雑な造りで申し訳ありません。他にも、ラベル無しでAnnotation書き込みを行うと例外エラーを起こしたりと、いろいろ不具合はあります。また、ラベルを付けた部分の枠線が画像中に残るようにできなかったり、不具合だらけですね。Linux環境であれば、もっといいツールがあるんですけどね・・・だれか、Windows版で作ってくれませんかねぇ。

お礼が遅くなってしまって申し訳ありません。
返信したつもりでしたが、投稿が反映されていませんでした。
この度はご対応いただきありがとうございました!
早速使わせていただいております。
短いですがお礼まで。

こんにちは、機械学習勉強中さん。

いえいえ、ご迷惑をおかけしました。会社で作ったコードを印刷して打ち込み、動いたのでそのままにしちゃいました。ちゃんとチェックしなきゃいけませんね。

ところで、このコードはkeras 1.2.2でないと動きません。最新のkeras(今は2.2.0)で使いたいときは、下記のサイトが参考になります。

http://d.hatena.ne.jp/natsutan/touch/20170318/1489851945

tensorflowも最新(1.8.0)にすればちゃんと動きました。本当は本文に書かないといけないのですが、この場を借りて紹介しておきます。ご参考まで。

質問失礼いたします。

VOC2007.pklというファイルが作成されません。
> python ・・・/get_data_from_XML.pyを入力してみたところ何もエラーなどは出ていないんですが、VOC2007.pklというファイルはできませんでした。
どうすれば解決できますか。

こんにちは、大学生さん。

コマンドの実行ですが、「PASCAL_VOC」フォルダと同じ階層に「get_data_from_XML.py」を移動後、「python get_data_from_XML.py」と実行されてますか?それとも、絶対パスで実行しているんでしょうか?

このコードの94行目付近にある以下のコード

pickle.dump(data,open('VOC2007.pkl','wb'))

を見る限り、実行したパスに「VOC2007.pkl」ができるはずですですが・・・あるいは、そのあたりを何か、いじられましたかね?

ssd_keras-masterはどこに置けばいいですか?

こんにちは、大学生さん。

特に決まりはありません。Linuxであれば、home/(ユーザー) の下に置いていただければいけるはずです。

もし、うちと同じWindows + Anaconda という環境なら、日本語名フォルダの下でなければいけるはず。会社のPCではc:\dl\の下に置いてます。

>Kerasというのはコードが書きやすくなる半面、学習データがブラックボックス化されるというか、どういう形式で書きこんでいるのかがわからなくなりますね。

ここは、kerasのせいではないと思いますが...
この最初のソースを書いた人の設計であり、フレームワークは関係してないですね。

自分的には、kerasは、keras自体のデータの入力形式も方法もわかりやすい方だと思いますが...

get_data_from_XML.pyの90行目に
# pickle.dump(data,open('VOC2007.p','wb')) と書いてありました。

これは、VOC2007.pklと書き換えた方がいいのですか?

こんにちは、大学生さん。

返信遅れました。コードを確認する間がなかったので……

書き忘れてましたが、まず88〜90行目のシャープ(#)を消してください。それで動くはずです。

私の方では、特にVOC2007.pのままでやってますが、そこもVOC2007.pklとしておいた方がいいかもしれません。記憶にないですが、多分私は後でファイル名を変えたようです。

質問失礼します。

Deeplearning素人なのですが、動画ではなく画像から物体を検出するための手順を教えていただけませんか?

こんにちは、大学生さん。

上記記事中で「検出(動画)」の項にある、「videotest_example.py」の中の「vid_test(‘〜‘)」の〜のところに動画のファイル名を入れるように書いてますが、あそこに静止画のファイル名を入れるといけます。

ただし、一瞬で結果が表示されて消えてしまうため、なんらか画像ファイルを出力するようにした方がよさそうです。

ありがとうごさいます。

独自データを作成しようとしたところ、

unknown label: aeroplane
unknown label: aeroplane
unknown label: aeroplane
unknown label: aeroplane
・・・

となってしまいます。

Deeplearning素人なので申し訳ありませんが、おしえていただけないでしょうか?

こんにちは、大学生さん。

上の「独自データでの学習」の項目の、「get_data_from_XML.py 」のラベルは書き換えましたでしょうか?

どこかでラベルを書き忘れているために出るエラーかと思われます。一度ご確認ください。

def _to_one_hot(self,name):
one_hot_vector = [0] * self.num_classes
if name == 'aeroplane': ←aeroplaneを書き換えました。
one_hot_vector[0] = 1
elif name == 'bicycle':
one_hot_vector[1] = 1

元々あったAnotationsに入っているaeroplaneのxmlファイルは削除したほうがいいですか?

こんにちは、大学生さん。

そのままでも大丈夫です。VOC2007のデータには、今回学習に使う20のラベル以外の名前の書かれたxmlファイルはたくさんありますが、プログラム中に記述したラベル以外は無視するため、いちいち削除したところであまり意味はありません。そのままでいいです。

こんにちは。
大変ためになる記事、ありがとうございます。

質問なのですが、
model.load_weights('weights_SSD300.hdf5', by_name=True)
となっている箇所は独自データ(pascal VOCに含まれていないような物体)を検出したい際の学習においても変更しなくても大丈夫でしょうか。

変更が必要な場合はどのようにして重みを出力すればよいかも教えていただけると幸いです。

こんにちは、毎日カレーさん。

最初の学習では、weight.SSD300.hdf5を使うしかないので、そのままご使用ください。ただ、一度独自データで学習すると、checkpointsというフォルダに〜.hdf5という学習器が生成されるため、その後独自データでの転移学習(画像の追加や新たなラベルでの学習)されるときは、その中から適当な学習器を選んで置き換えてください。

このコード自体が、0からの学習ができない仕様のため、最初はなんらかの学習器を読み込んで使うしかありません。最近公開されているディープラーニングのプログラムコードはこういうものが多いです。ですが、これでまあまあ上手くいくので、一度お試しください。

返信ありがとうございます。

やはり最初はそのまま使うしかないのですね。
一度学習して、画像を追加するなりしながら試していこうと思います。

こんにちは、毎日カレーさん。

この手の技術は、少しづつ試すしかないですね。頑張ってください。私もかれこれ1年半ほどディープラーニングに関わってますが、実際に使ってみると理解が早いと思います。オープンソースでこれほどのコードが手に入る時代です。試してみるに限ると思います。

こんにちは!この記事を参考にgithubから構築をしています。
windows10でanacondaを用いており、各バージョンは、Keras==1.2.2, Opencv==3.1.0, tensorflow==1.2.0を使用して行いました。その結果、CPUでのtrain_ssd_keras.pyの実行は可能になりました。
しかし、私はGPUでの実行を行いたいため、上記のバージョンのtensorflowをアンインストールし、tensorflow-gpu==1.2.0をインストールした結果、実行をすることができなくなってしまいました。
このSSD_KerasをGPUで動作させるには、どのようにすれば良いか教えていただきたいです。よろしくお願いします。

こんにちは、リーさん。

おそらくですが、Kerasも再インストールが必要かと思われます。kerasをアンインストールして、再インストールすると使えると思います。

今だと、1.9以上のTensorFlow、Kerasは2以上にするのがいいかもしれません。私も会社の環境で最新のkerasと1.9のTensorFlowにしたうえで、

http://d.hatena.ne.jp/natsutan/touch/20170318/1489851945

を参考にコードを書き換えたところ、使えました。

最新版のTensorFlowやKerasの方が実行効率がやや上がっていたり、不具合が減っているようなので、なるべくなら細心にしたいところですね。ご参考まで。

arkoujiさん返信ありがとうございます!

kerasも再インストールを行ってみましたが、実行の結果、No Module tensorflowとなってしまい、実行できませんでした涙  
もちろん、tensorflow==1.2.0はアンインストールしtensorflow-gpu==1.2.0はインストール行ってます、、、

できれば、arkoujiさんがgpu環境で実行できた時のインストール環境(ex. tensorflow-gpu==1.9.0 , matplotlib==... など)を一覧で教えていただくことはできないでしょうか??

こんにちは、リーさん。

返信遅れました。とりあえず、pip listでの表示を張り付けておきます。
(自宅のWindows版Anaconda3 4.4.0です)
absl-py 0.2.2
appdirs 1.4.0
astor 0.6.2
bleach 1.5.0
boto 2.48.0
boto3 1.7.39
botocore 1.10.39
bz2file 0.98
certifi 2017.11.5
chardet 3.0.4
cmake 0.6.0
colorama 0.3.9
cycler 0.10.0
Cython 0.25.2
decorator 4.1.2
docutils 0.14
entrypoints 0.2.3
gast 0.2.0
gensim 3.4.0
grpcio 1.12.1
h5py 2.7.0
html5lib 0.9999999
idna 2.6
ipykernel 4.6.1
ipython 6.1.0
ipython-genutils 0.2.0
ipywidgets 6.0.0
Janome 0.3.6
jedi 0.10.2
Jinja2 2.9.6
jmespath 0.9.3
jsonschema 2.6.0
jupyter 1.0.0
jupyter-client 5.0.1
jupyter-console 5.1.0
jupyter-core 4.3.0
Keras 2.2.0
Keras-Applications 1.0.2
Keras-Preprocessing 1.0.1
lxml 3.8.0
Markdown 2.6.11
MarkupSafe 1.0
matplotlib 2.0.2
mistune 0.7.4
nbconvert 5.2.1
nbformat 4.3.0
networkx 1.11
notebook 5.0.0
numpy 1.13.3
olefile 0.44
packaging 16.8
pandas 0.20.3
pandocfilters 1.4.1
pickleshare 0.7.4
Pillow 4.2.1
pip 10.0.1
prompt-toolkit 1.0.14
protobuf 3.6.0
Pygments 2.2.0
pyparsing 2.2.0
pystan 2.17.1.0
python-dateutil 2.6.1
pytz 2017.2
PyWavelets 0.5.2
PyYAML 3.12
pyzmq 16.0.2
qtconsole 4.3.0
requests 2.18.4
s3transfer 0.1.13
scikit-image 0.13.0
scikit-learn 0.18.1
scipy 1.0.0
selectivesearch 0.4
setuptools 34.0.1
simplegeneric 0.8.1
six 1.11.0
smart-open 1.5.7
tensorboard 1.8.0
tensorflow 0.12.0rc1
tensorflow-gpu 1.8.0
termcolor 1.1.0
testpath 0.3.1
tflearn 0.3.2
Theano 1.0.1
tornado 4.5.1
tqdm 4.19.5
traitlets 4.3.2
urllib3 1.22
wcwidth 0.1.7
webencodings 0.5.1
Werkzeug 0.14.1
wheel 0.29.0
widgetsnbextension 2.0.0
win-unicode-console 0.5

ほとんどAnacondaについていたものばかりで、自分でインストールしたものはほとんどありません。
また、見ていただくとわかりますが、CPU版TensorFlowを残したまま(0.12.0rc1)、GPU版TensorFlow-gpu(ここでは1.8.0)をインストールしております。これでも動いてますね。

なお、会社では1.9.0を使っております。

初めまして。この記事を参考に独自データをつかってやっているものです。
質問なのですが、train_ssd_keras.pyを実行することはできたのですが、
Epoch1/30 4086/4087の時点で以下のようなエラーがはいてしまいました。
ValueError: Error when checking input: expected input_1 to have shape (300, 300, 3) but got array with shape (300, 300, 4)
これはどういうことなのでしょうか。もしなにかわかるならば教えていただきたいです。
ちなみに独自で集めた画像のサイズはバラバラでやっていまして、もしかしたら影響があるのでしょうか。

こんにちは、taguseiさん。

うーん、よくわかりませんが、以下のIssue が近いですかね?

https://github.com/rykov8/ssd_keras/issues/84

どうやら、グレースケールの画像を使ってるとこうなるようなことが書かれてるっぽいですが……とりあえず、こちらでは起こったことのないエラーですね。

ちなみに、ばらばらのサイズは問題ないはずです。こちらでも経験済みですが、特にエラーになったことはないです。ただ、小さすぎる画像は不具合を起こすことがあったような……すいません、あまりちゃんとした回答はできませんね。

arkoujiさん、返信ありがとうございます。
もう一度やり直して、手順の通りやっていると返信していただいたようなエラーが起きました。
解決策の通り行ってみると、画像ファイルがjpgとpngが混ざっていたのが問題だったような気がします。ちなみに私はpngの画像データはすべて消して、jpgの画像データだけで行うと無事成功しました。助かりました、ありがとうございました。
このデータを使ってカメラからの認識ができれば思っています。
もし、またなにかわからないことがでてきたら教えていただきたいです。

こんにちは、taguseiさん。

ああ、そういえばこのコードはjpgオンリーでしたね。予めpngファイルは変換が必要です。

一応、カメラ画像からの認識コードは付いていました。使ったことがないので、なんとも言えませんが……

ところで、SSDに対抗意識を燃やすyoloもバージョン3を出しています。tensorflow+keras版も出ているので、そちらも検討してみるといいかもしれません。確かに認識速度と数は多いですが、条件次第ではSSDの方が良かったり、yoloの方が良かったり……ただ、手法を2種類くらい持っておくのは便利です。

はじめまして。
この記事にある検出(動画)の項目の

「ここでは、動画を使ったリアルタイム検出を行います。
まず「testing_utils」というフォルダに、物体検出させたい動画を入れます(ホームビデオなど)。
続いて、「videotest_example.py」を開きます。18行目の「model.load_weights('~')」の' '内に学習済みデータのファイル名(ex. ../checkpoints/weights.96-2.83.hdf5)を入れて、24行目の「vid_test.run('~')」の' '内には動画ファイル名を入れます。」

までは行えたのですが、その次の

「以下のような画像が出てくるはずです。」

の部分がわかりません。
なんのプログラムを実行したらそうなるのでしょうか?

こんにちは、benkyoさん。

言われてみれば、抜けてますね。まさに編集中のコードを実行します。

python videotest_example.py

そうすると、物体検出の画像が出てきます。お試しください。

ご返信ありがとうございます。
うまくいきました。
このブログのおかげもあり、これから物体認識についてどんどん取り組んでいこうと思います。
ありがとうございました。

たびたびの質問すみません
画像からの学習が終了し、動画からの検出を行おうと思って上記のようにvideotest_example.pyを実行したのですが、以下のようなエラーが出てしまい、解決できません...
どうすればよいのでしょうか?

Dimension 3 in both shapes must be equal, but are 60 and 63. Shapes are [3,3,512,60] and [3,3,512,63]. for 'Assign_43' (op: 'Assign') with input shapes: [3,3,512,60], [3,3,512,63].

こんにちは、benkyoさん。

うーん、よくわかりませんね。以下のissueがよく似てますけど、こちらもよくわかりませんでした。

https://github.com/rykov8/ssd_keras/issues/136

なんとなくですが、ニューラルネットワークのどこかが崩れちゃったんですかね?でもこのコードでは、そういうのはできない気がしますが。

返信ありがとうございます。
これはpythonやkeras、tensorflow、をインストールしなおしたほうが良いんでしょうか...?

こんにちは、benkyoさん。

そういうレベルのものではないと思います。多分、同じコードを別のPCに持っていっても起こる類のことのように思います。

video_example.pyで読み込ませる学習器を「weights_SSD300.hdf5」に戻しても、同じエラーが出ますか?もし出ないようなら、独自データで学習させて作った学習器(weights_〜.hdf5)がおかしいと分かるので、対処のしようがあるかもしれません。

返信ありがとうございます。

weights_SSD300.hdf5でやってみたものの、やはり同じエラーが出てしまいます。
これは対処が難しいでしょうか?

こんにちは、benkyoさん。

どこかコードをいじってしまってますね。もう一度Githubからオリジナルのコードを持ってきた方が良さそうです。今わかるのは、それくらいでしょうか。

返信ありがとうございます。

この件に関しまして、無事解決しましたのでご報告させていただきます。
エラーの理由はおそらくvideotext_example.pyの中身の
class_name =
以降にある最初の
"background"
を誤って削除したからだと思われます。

お騒がせしてすみませんでした。

こんにちは、benkyoさん。

あ…それでエラーが出てたんですね。なるほど、私も勉強になります。

ところで、今まさに物体検出を会社でトライ中です。このコードも使えないか、検討中。これはこれでよくできたコードなので、便利ですね。

はじめまして。
こちらのブログを参考に動画から物体を検出させたのですが、「SSD_result」のウィンドウを閉じようとしても何回も復活してしまいます。
prompt自体を終了させる以外に、どうしたらSSD_resultのウィンドウを閉じることができるのでしょうか。

こんにちは、asさん。

プロンプトで「Ctrl + C」を押して止まりませんか?おっしゃる通り、画像の方を閉じても、実行コマンドが動き続ける限り復活します。私もしょっちゅう使ってます。多分、それで止まると思います。

返信ありがとうございます。おかげさまで解決しました。

お久しぶりです,、taguseiです。
今回、独自で画像データを大量に用意できたため、もう一度やってみようと思っているのですが
不明な点があったのでもし知っていらっしゃれば教えていただきたいです。
今回、使用する画像の大きさが640×480なのですが、train_ssd_keras.pyのソースコードに
input_shape = (300, 300, 3)
と記述してあるところは変更しないでもよろしいのでしょうか?

こんにちは、taguseiさん。

input_shapeは変えなくていいです。内部で勝手にそのサイズに変えて学習してくれてるようです。
どうしても解像度を変えたい場合、その先のニューラルネットワークも変えないといけなくなるはずです。解像度を上げれば精度が上がるかというとそうとばかりも言えないので、まずはそのまま使ったほうが良さそうです。

返信ありがとうございます。
おっしゃっている通りであれば、画像は640×480の大きさのままで画像の大きさに関してソースコードの記述は変更しなくても大丈夫ということでよろしいでしょうか。
何度もすみません。

はじめまして。突然ですが私は今この記事を参考に独自データをつかって麻雀牌の学習させようとしています。
独自データとそのアノテーションデータを用意し、get_data_from_XML.pyとtrain_ssd_keras.pyに変更を適用して実行したのですが、
IOError: [Errno 2] No such file or directory: './VOCdevkit/VOC2007/ma-jyanhaiIMG/0078.jpg'
ValueError: output of generator should be a tuple (x, y, sample_weight) or (x, y). Found: None
というようなエラーが出てしまいます。
画像やアノテーションデータはJPEGImagesのような元からあるファイルとは別に作ったのですがそれが原因なのでしょうか・・・
それともどこか変更するところが足りないのでしょうか?

すいません解決しましたw
/ssd_keras/VOC2007/の中にフォルダ作って終わりだと思って/ssd_keras/VOCdevkit/の中にも作るのを忘れていたのが原因でした(/ω\)ハズカシー
また詰まった時には相談させていただきますので、その時は是非お願いします(*_ _)人

独自画像のみを学習させるため、train_ssd_keras.py の NUM_CLASSES を 3 にして実行したのですがエラーとなりました。

File "/root/.local/lib/python3.5/site-packages/trainer/ssd_utils.py", line 149, in assign_boxes
assignment[:, 5:-8][best_iou_mask] = boxes[best_iou_idx, 4:]
ValueError: shape mismatch: value array of shape (15,2) could not be broadcast to indexing result of shape (15,20)

get_data_from_XML.py : self.num_classes = 2 にして pkl 生成

因みに NUM_CLASSES を22にして、クラスを一つ増やして実行すると成功しました。

何かヒントなどありますでしょうか。

とても良い記事ありがとうございます。 nvidia jetson tx2で試していますが、学習開始直後に落ちてしまいます。 もしおわかりでしたら教えていただきたいです。

環境
nvidia jetson tx2
Python 2.7.12
Keras 2.2.0
tensorflow 1.9.0

落ちたときのターミナルの内容
may mean that there could be performance gains if more memory were available.
1/250 [..............................] - ETA: 1:16:13 - loss: 7.12462019-01-27 09:08:59.319997: W tensorflow/core/framework/op_kernel.cc:1318] OP_REQUIRES failed at where_op.cc:286 : Internal: WhereOp: Could not launch cub::DeviceReduce::Sum to count number of true / nonzero indices. temp_storage_bytes: 1, status: too many resources requested for launch
Traceback (most recent call last):
File "1_ssd_train.py", line 255, in
workers=1)
File "/usr/local/lib/python2.7/dist-packages/keras/legacy/interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1426, in fit_generator
initial_epoch=initial_epoch)
File "/usr/local/lib/python2.7/dist-packages/keras/engine/training_generator.py", line 191, in fit_generator
class_weight=class_weight)
File "/usr/local/lib/python2.7/dist-packages/keras/engine/training.py", line 1220, in train_on_batch
outputs = self.train_function(ins)
File "/usr/local/lib/python2.7/dist-packages/keras/backend/tensorflow_backend.py", line 2661, in __call__
return self._call(inputs)
File "/usr/local/lib/python2.7/dist-packages/keras/backend/tensorflow_backend.py", line 2631, in _call
fetched = self._callable_fn(*array_vals)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/client/session.py", line 1454, in __call__
self._session._session, self._handle, args, status, None)
File "/usr/local/lib/python2.7/dist-packages/tensorflow/python/framework/errors_impl.py", line 519, in __exit__
c_api.TF_GetCode(self.status.status))
tensorflow.python.framework.errors_impl.InternalError: WhereOp: Could not launch cub::DeviceReduce::Sum to count number of true / nonzero indices. temp_storage_bytes: 1, status: too many resources requested for launch
[[Node: loss/predictions_loss/boolean_mask/Where = Where[T=DT_BOOL, _device="/job:localhost/replica:0/task:0/device:GPU:0"](loss/predictions_loss/boolean_mask/Reshape_1)]]
[[Node: loss/mul/_869 = _Recv[client_terminated=false, recv_device="/job:localhost/replica:0/task:0/device:CPU:0", send_device="/job:localhost/replica:0/task:0/device:GPU:0", send_device_incarnation=1, tensor_name="edge_3936_loss/mul", tensor_type=DT_FLOAT, _device="/job:localhost/replica:0/task:0/device:CPU:0"]()]]

因みにpython3で実行したいのですがpip3がうまく入らず断念。

こんにちは、??さん。

いまいちエラーの内容はわかりませんが、なんとなく必要なライブラリが入ってなさそうな感じのメッセージですね。
もしかしたらですが、python 2.7とtensorflowとkerasの組み合わせがまずいんでしょうかね。

最近、Raspberry Piにtensorflow+kerasの組み合わせを、python 2.7でやろうとしたんですが、頑として動きませんでした。なんとかしてpython3で構築したら、なんとか動くようになりました。

あと、ありがちなのは、tensorflowやkeras、opencvなどを入れているうちに、使っているライブラリが未対応のものが上書きされて、動かなくなるというものでした。エラーの最終行だけをgoogleの検索に入れてググると、対応していないライブラリが出てきて入れなおし……というのを繰り返してました。何度かやってるうちに、うまく行きました。

jetson TX2なら、そのあたりいろいろとノウハウがありそうな気もしますが、実機がないのでよく分かりません。申し訳ないです。

jetson tx2では諦め、 python3(3.6.7)で環境構築し、nvidia xavierで実行できました。 

やはりpython3でしか動かないと思います。

環境構築にめっちゃ試行錯誤しました。

物体検出を試行するにあたって、非常に参考になりました。
ありがとうございます。

二点ほど、アノテーションについてお尋ねしたいのですが、
1.
>「ImageSets/Main」にある「trainval.txt」に、上で作られた「trainval.txt」の中身を追記します。
こちらは、どういった意図がある作業なのでしょうか。
この部分を行わなくても、当方の環境では学習コードが実行できました。
そのモデルを使い、動画で検出テストした結果も特に問題はないように見えるのですが・・・。
2.
VoTTというアノテーションツールをご存知でしょうか。
それを使って同じように学習コードを実行すると、学習の際にエラーが発生します。
・No such file or directory ...('画像ファイルのパス(なぜか拡張子がついてない?)')
貴殿のアノテーションツールを使えば、1.に記載した通り問題なく学習できており、
xmlファイル生成(アノテーション)以外は同じ手順・構成で実行しています。
また、エラーメッセージが示す画像のパスを確認しても、
しっかりと画像ファイルは存在しているんですよね。
違いといえばxmlの構成ぐらいかなとは思いますが・・・。

何かお気付きの点があればお知恵を頂戴したく、
よろしくお願い申し上げます。

こんにちは、hogeさん。

まず一つ目ですが、get_data_from_XML.pyが「trainval.txt」を読んでいたはず……なのですが、そう言われると自信がないですね。
Pascal VOC 2007形式のデータを使うコードでは、このtrainval.txtを使うコードが多いので、思わずかきこんだかけかもしれません。ちなみに、YOLOあたりだと使っていたはずです。

2つ目ですが、よくわかりませんね……まさかとは思うのですが、改行コードあたりで引っかかるのか、それくらいですね。

とにかく、VOC2007形式のアノテーションをさせたくて無理矢理作ったツールなので、癖はありますが、xmlファイルはちゃんと吐き出すようになっているはずです。実際、うちの業務でも使った実績ありです。もっとも、使いにくいとは言われてますが……

回答ありがとうございます。

2つ目については解決しました。
VoTTが生成するxmlファイルのタグに、拡張子がつかない仕様であることが原因でした。
つまり「画像」データを参照していなかったんですね。
すべてのxmlファイルを編集して.jpg拡張子を付与したところ、学習が行われました。

1つ目についてはやはりわからないですね。
YOLOは使ったことないのですが、このデータが必要になる旨、認識しておきます。
また何かお気づきになりましたらまた教えていただければ幸いです。

お手数をおかけしました。

1つ目ですが,get_data_from_XML.pyは「VOC2007/Annotations/」フォルダ内の全ファイルを
リストとして受け取ってpklファイルを作成するようになっているようです.
なので,上記フォルダにxmlファイルがあればOKなようです.
逆に,xmlファイル以外のものがあればエラーが出ると思われます.

ただ,私は管理人さんがこの記事でtrainval.txtに言及されていたことで,
YOLOではないですが,別のコードに当たったときに,学習データのロードで
大ハマりせずに済んだので,その節はお世話になりました.
ありがとうございました.

こんにちは、フニクリフニクラさん。

やはりこっちでは不要だったんですね。要るものだという前提で記事を書いてました。ちゃんと調べたほうがいいですね。

ただ、いろいろな物体検出コードを使うときには、とりあえずtrainval.txtは作っといた方がいいのは間違いないですね。

大変勉強になります。
併せて、基本的なことを教えていただけないでしょうか。

0から学習する?(model.load_weights('weights_SSD300.hdf5', by_name=True)をコメントアウトする)のと、
初期重みにweights_SSD300.hdf5を使う場合では、
後者の方が圧倒的にオブジェクトを検出します。
※まったく新しい物体に対して学習し、検出を試みているのですが、明らかに検出率が違います。

これは所謂、転移学習というものの効果なのでしょうか。
(理想的な重みに近づいた状態で学習をスタートできる、みたいな解釈でよいのでしょうか。)

こんにちは、hogeさん。

一見すると余計なデータが入ってしまう転移学習の方が、精度が高いとされてます。特にSSDやYOLOだと、私が試した限りでは転移学習でないとうまくいきませんでした。ゼロからでは、変な局地解に陥っちゃうとでもいうんでしょうか?そんな感じでした。

以下記事とあわせて大変お世話になっています。
http://arkouji.cocolog-nifty.com/blog/2018/07/yolo-v3-keras22.html

独自データによる学習実行で学習させてみたのですが以下エラーが出てしまいます。原因に見当がつくようでしたら教えていただきたいです。
VOC2007での学習はエラーが生じないので、独自データで動かす際に限りうまくいかない模様です。

ちなみにYOLOのほうでは独自データによる学習⇒推論までできました!ありがとうございます。

94/95 [============================>.] - ETA: 0s - loss: 2.2269Traceback (most recent call last):
File "train_ssd_keras.py", line 247, in <module>
nb_worker=1)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\engine\training.py", line 2244, in fit_generator
max_queue_size=max_queue_size)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\legacy\interfaces.py", line 91, in wrapper
return func(*args, **kwargs)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\engine\training.py", line 2362, in evaluate_generator
generator_output = next(output_generator)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\utils\data_utils.py", line 793, in get
six.reraise(value.__class__, value, value.__traceback__)
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\six.py", line 693, in reraise
raise value
File "C:\Users\user1001\Anaconda3\envs\tf352\lib\site-packages\keras\utils\data_utils.py", line 658, in _data_generator_task
generator_output = next(self._generator)
File "train_ssd_keras.py", line 205, in generate
tmp_inp = np.array(inputs)
ValueError: could not broadcast input array from shape (300,300,3) into shape (300,300)

RGBとかグレースケールとかのお話でしょうかね?
学習データは、10KB~500KB程度のカラー画像です。

こんにちは、とおさん。返信遅れまして、申し訳ありません。

配列の形状が合わないと言ってるようなので、なんとなくですが、画像ファイルじゃないものを読み込もうとしているようなエラーにも見えます。今言えるのは、それくらいでしょうか?

それくらいしかわかりませんね。すいません。

コメントを書く

(ウェブ上には掲載しません)

トラックバック


この記事へのトラックバック一覧です: TensorFlow+KerasでSSDを独自データで使えるようにしてみた:

« カメラ付きのワインセラー”Plum wine system” | トップページ | Lenovo G580が我が家にやってきた »

当ブログ内検索

  • カスタム検索

スポンサード リンク

ブログ村

無料ブログはココログ