TensorFlow+KerasでSSDを独自データで使えるようにしてみた
物体検出コードといえば以前「ディープラーニングで一般物体検出する手法”YOLO”のTensorFlow版で独自データセットを使えるようにしてみた: EeePCの軌跡」という記事で紹介したYOLOv1という手法を使えるようにしたのですが、このYOLOv1、精度はいまいち。
ということで、最新のSSD or YOLOv2を使えるようにしたいなぁと考え、何とかこのSSD(Single Shot MultiBox Detector)を使えるようにしました。
コードの入手先はこちら。
参考サイトはこちら。
物体検出アルゴリズム(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に変更しておいてください。
先の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('~')」の' '内には動画ファイル名を入れます。
以下のような画像が出てくるはずです。
うちの環境では、7FPS程度しか出ません。
不思議と元データ「weights_SSD300.hdf5」を使うと、13FPS出るんですけどね。学習データによって倍もフレームレートが変わるという理由がよくわかりませんね。
ともかく、精度はまあまあありそうです。
独自データでの学習
さて、これまVOC2007のデータを使った話。独自データを使うにはどうするのか?
まずは、独自データとなる画像を集めます。これは必須。
続いて、「AnnotationTool.exe」をダウンロードします。
私がとりあえず作った、Windows上で動かすアノテーションデータ作成ソフトです。
使い方は以下。
-----------------------------------------------------------------------
① まずアノテーションファイル(*.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、おすすめです。
« カメラ付きのワインセラー”Plum wine system” | トップページ | Lenovo G580が我が家にやってきた »
「数値解析系」カテゴリの記事
- 純日本産なローカルLLM「Tanuki-8B」を試してみた(2024.09.02)
- 東京のセールスフォースに行ってきました(2024.07.24)
- ローカルLLM「Llama-3-ELYZA-JP-8B」にいろいろ聞いてみた(2024.07.01)
- ElyzaのLlama3ベースの言語モデル「Llama-3-ELYZA-JP-8B」のRAGが予想以上に賢かった件(2024.06.27)
- Googleの生成AI「Gemini 1.5 Pro」を使ったサービス「notebookLM」がすごいらしいので試してみた(2024.06.24)
コメント
« カメラ付きのワインセラー”Plum wine system” | トップページ | Lenovo G580が我が家にやってきた »
過去記事への投稿失礼します。
非常にためになる記事をありがとうございます。
一通り動いたのですが、気づいたことがあるのでご連絡させていただきます。
独自データでのget_data_from_XML.py実行時にエラーになったので調べてみたところ、となっていますが、
AnnotationTool.exeを実行してできる .xml ファイルの3行目が
投稿: 機会学習勉強中 | 2018年6月13日 (水) 14時49分
こんにちは、機会学習勉強中さん。
ご指摘ありがとうございます。ただ、今ちょうど出先でして、なんとか今夜中に対応したいと思います。それまでお待ちいただけますか?
投稿: arkouji | 2018年6月14日 (木) 12時21分
ご連絡いただきありがとうございます。
また、ご対応いただけるとのことで、大変ありがとうございます!
昨日のコメント内で肝心な部分が消えていたので、今更ですが念のため改めて書かせていただきます。
3行目のspirceとなっている箇所ですが、正しくはsourceかと思いますので、ご確認いただければ幸いです。
投稿: 機械学習勉強中 | 2018年6月14日 (木) 14時52分
こんにちは、機械学習勉強中 さん。
たった今、アップいたしました。おっしゃる通り、”source”が”spirce”になってますね。ソースを直し、修正できていることを確認いたしました。
世の中にあるAnnotationツールに比べると、ずいぶんと雑な造りで申し訳ありません。他にも、ラベル無しでAnnotation書き込みを行うと例外エラーを起こしたりと、いろいろ不具合はあります。また、ラベルを付けた部分の枠線が画像中に残るようにできなかったり、不具合だらけですね。Linux環境であれば、もっといいツールがあるんですけどね・・・だれか、Windows版で作ってくれませんかねぇ。
投稿: arkouji | 2018年6月14日 (木) 20時16分
お礼が遅くなってしまって申し訳ありません。
返信したつもりでしたが、投稿が反映されていませんでした。
この度はご対応いただきありがとうございました!
早速使わせていただいております。
短いですがお礼まで。
投稿: 機械学習勉強中 | 2018年6月20日 (水) 10時13分
こんにちは、機械学習勉強中さん。
いえいえ、ご迷惑をおかけしました。会社で作ったコードを印刷して打ち込み、動いたのでそのままにしちゃいました。ちゃんとチェックしなきゃいけませんね。
ところで、このコードはkeras 1.2.2でないと動きません。最新のkeras(今は2.2.0)で使いたいときは、下記のサイトが参考になります。
http://d.hatena.ne.jp/natsutan/touch/20170318/1489851945
tensorflowも最新(1.8.0)にすればちゃんと動きました。本当は本文に書かないといけないのですが、この場を借りて紹介しておきます。ご参考まで。
投稿: arkouji | 2018年6月20日 (水) 18時58分
質問失礼いたします。
VOC2007.pklというファイルが作成されません。
> python ・・・/get_data_from_XML.pyを入力してみたところ何もエラーなどは出ていないんですが、VOC2007.pklというファイルはできませんでした。
どうすれば解決できますか。
投稿: 大学生 | 2018年8月12日 (日) 01時01分
こんにちは、大学生さん。
コマンドの実行ですが、「PASCAL_VOC」フォルダと同じ階層に「get_data_from_XML.py」を移動後、「python get_data_from_XML.py」と実行されてますか?それとも、絶対パスで実行しているんでしょうか?
このコードの94行目付近にある以下のコード
pickle.dump(data,open('VOC2007.pkl','wb'))
を見る限り、実行したパスに「VOC2007.pkl」ができるはずですですが・・・あるいは、そのあたりを何か、いじられましたかね?
投稿: arkouji | 2018年8月12日 (日) 11時55分
ssd_keras-masterはどこに置けばいいですか?
投稿: 大学生 | 2018年8月12日 (日) 18時14分
こんにちは、大学生さん。
特に決まりはありません。Linuxであれば、home/(ユーザー) の下に置いていただければいけるはずです。
もし、うちと同じWindows + Anaconda という環境なら、日本語名フォルダの下でなければいけるはず。会社のPCではc:\dl\の下に置いてます。
投稿: arkouji | 2018年8月13日 (月) 04時21分
>Kerasというのはコードが書きやすくなる半面、学習データがブラックボックス化されるというか、どういう形式で書きこんでいるのかがわからなくなりますね。
ここは、kerasのせいではないと思いますが...
この最初のソースを書いた人の設計であり、フレームワークは関係してないですね。
自分的には、kerasは、keras自体のデータの入力形式も方法もわかりやすい方だと思いますが...
投稿: taashi | 2018年8月16日 (木) 17時07分
get_data_from_XML.pyの90行目に
# pickle.dump(data,open('VOC2007.p','wb')) と書いてありました。
これは、VOC2007.pklと書き換えた方がいいのですか?
投稿: 大学生 | 2018年8月21日 (火) 13時15分
こんにちは、大学生さん。
返信遅れました。コードを確認する間がなかったので……
書き忘れてましたが、まず88〜90行目のシャープ(#)を消してください。それで動くはずです。
私の方では、特にVOC2007.pのままでやってますが、そこもVOC2007.pklとしておいた方がいいかもしれません。記憶にないですが、多分私は後でファイル名を変えたようです。
投稿: arkouji | 2018年8月23日 (木) 08時06分
質問失礼します。
Deeplearning素人なのですが、動画ではなく画像から物体を検出するための手順を教えていただけませんか?
投稿: 大学生 | 2018年8月24日 (金) 14時37分
こんにちは、大学生さん。
上記記事中で「検出(動画)」の項にある、「videotest_example.py」の中の「vid_test(‘〜‘)」の〜のところに動画のファイル名を入れるように書いてますが、あそこに静止画のファイル名を入れるといけます。
ただし、一瞬で結果が表示されて消えてしまうため、なんらか画像ファイルを出力するようにした方がよさそうです。
投稿: arkouji | 2018年8月25日 (土) 15時12分
ありがとうごさいます。
独自データを作成しようとしたところ、
unknown label: aeroplane
unknown label: aeroplane
unknown label: aeroplane
unknown label: aeroplane
・・・
となってしまいます。
Deeplearning素人なので申し訳ありませんが、おしえていただけないでしょうか?
投稿: 大学生 | 2018年8月29日 (水) 13時40分
こんにちは、大学生さん。
上の「独自データでの学習」の項目の、「get_data_from_XML.py 」のラベルは書き換えましたでしょうか?
どこかでラベルを書き忘れているために出るエラーかと思われます。一度ご確認ください。
投稿: arkouji | 2018年8月29日 (水) 18時46分
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ファイルは削除したほうがいいですか?
投稿: 大学生 | 2018年8月31日 (金) 13時21分
こんにちは、大学生さん。
そのままでも大丈夫です。VOC2007のデータには、今回学習に使う20のラベル以外の名前の書かれたxmlファイルはたくさんありますが、プログラム中に記述したラベル以外は無視するため、いちいち削除したところであまり意味はありません。そのままでいいです。
投稿: arkouji | 2018年9月 1日 (土) 20時53分
こんにちは。
大変ためになる記事、ありがとうございます。
質問なのですが、
model.load_weights('weights_SSD300.hdf5', by_name=True)
となっている箇所は独自データ(pascal VOCに含まれていないような物体)を検出したい際の学習においても変更しなくても大丈夫でしょうか。
変更が必要な場合はどのようにして重みを出力すればよいかも教えていただけると幸いです。
投稿: 毎日カレー | 2018年9月 5日 (水) 09時36分
こんにちは、毎日カレーさん。
最初の学習では、weight.SSD300.hdf5を使うしかないので、そのままご使用ください。ただ、一度独自データで学習すると、checkpointsというフォルダに〜.hdf5という学習器が生成されるため、その後独自データでの転移学習(画像の追加や新たなラベルでの学習)されるときは、その中から適当な学習器を選んで置き換えてください。
このコード自体が、0からの学習ができない仕様のため、最初はなんらかの学習器を読み込んで使うしかありません。最近公開されているディープラーニングのプログラムコードはこういうものが多いです。ですが、これでまあまあ上手くいくので、一度お試しください。
投稿: arkouji | 2018年9月 8日 (土) 07時28分
返信ありがとうございます。
やはり最初はそのまま使うしかないのですね。
一度学習して、画像を追加するなりしながら試していこうと思います。
投稿: 毎日カレー | 2018年9月18日 (火) 14時03分
こんにちは、毎日カレーさん。
この手の技術は、少しづつ試すしかないですね。頑張ってください。私もかれこれ1年半ほどディープラーニングに関わってますが、実際に使ってみると理解が早いと思います。オープンソースでこれほどのコードが手に入る時代です。試してみるに限ると思います。
投稿: arkouji | 2018年9月19日 (水) 19時55分
こんにちは!この記事を参考に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で動作させるには、どのようにすれば良いか教えていただきたいです。よろしくお願いします。
投稿: リー | 2018年9月28日 (金) 14時27分
こんにちは、リーさん。
おそらくですが、Kerasも再インストールが必要かと思われます。kerasをアンインストールして、再インストールすると使えると思います。
今だと、1.9以上のTensorFlow、Kerasは2以上にするのがいいかもしれません。私も会社の環境で最新のkerasと1.9のTensorFlowにしたうえで、
http://d.hatena.ne.jp/natsutan/touch/20170318/1489851945
を参考にコードを書き換えたところ、使えました。
最新版のTensorFlowやKerasの方が実行効率がやや上がっていたり、不具合が減っているようなので、なるべくなら細心にしたいところですね。ご参考まで。
投稿: arkouji | 2018年9月30日 (日) 11時26分
arkoujiさん返信ありがとうございます!
kerasも再インストールを行ってみましたが、実行の結果、No Module tensorflowとなってしまい、実行できませんでした涙
もちろん、tensorflow==1.2.0はアンインストールしtensorflow-gpu==1.2.0はインストール行ってます、、、
できれば、arkoujiさんがgpu環境で実行できた時のインストール環境(ex. tensorflow-gpu==1.9.0 , matplotlib==... など)を一覧で教えていただくことはできないでしょうか??
投稿: リー | 2018年10月 2日 (火) 19時17分
こんにちは、リーさん。
返信遅れました。とりあえず、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を使っております。
投稿: arkouji | 2018年10月 5日 (金) 21時42分
初めまして。この記事を参考に独自データをつかってやっているものです。
質問なのですが、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 | 2018年10月11日 (木) 10時23分
こんにちは、taguseiさん。
うーん、よくわかりませんが、以下のIssue が近いですかね?
https://github.com/rykov8/ssd_keras/issues/84
どうやら、グレースケールの画像を使ってるとこうなるようなことが書かれてるっぽいですが……とりあえず、こちらでは起こったことのないエラーですね。
ちなみに、ばらばらのサイズは問題ないはずです。こちらでも経験済みですが、特にエラーになったことはないです。ただ、小さすぎる画像は不具合を起こすことがあったような……すいません、あまりちゃんとした回答はできませんね。
投稿: arkouji | 2018年10月11日 (木) 17時47分
arkoujiさん、返信ありがとうございます。
もう一度やり直して、手順の通りやっていると返信していただいたようなエラーが起きました。
解決策の通り行ってみると、画像ファイルがjpgとpngが混ざっていたのが問題だったような気がします。ちなみに私はpngの画像データはすべて消して、jpgの画像データだけで行うと無事成功しました。助かりました、ありがとうございました。
このデータを使ってカメラからの認識ができれば思っています。
もし、またなにかわからないことがでてきたら教えていただきたいです。
投稿: tagusei | 2018年10月13日 (土) 09時43分
こんにちは、taguseiさん。
ああ、そういえばこのコードはjpgオンリーでしたね。予めpngファイルは変換が必要です。
一応、カメラ画像からの認識コードは付いていました。使ったことがないので、なんとも言えませんが……
ところで、SSDに対抗意識を燃やすyoloもバージョン3を出しています。tensorflow+keras版も出ているので、そちらも検討してみるといいかもしれません。確かに認識速度と数は多いですが、条件次第ではSSDの方が良かったり、yoloの方が良かったり……ただ、手法を2種類くらい持っておくのは便利です。
投稿: arkouji | 2018年10月13日 (土) 19時47分
はじめまして。
この記事にある検出(動画)の項目の
「ここでは、動画を使ったリアルタイム検出を行います。
まず「testing_utils」というフォルダに、物体検出させたい動画を入れます(ホームビデオなど)。
続いて、「videotest_example.py」を開きます。18行目の「model.load_weights('~')」の' '内に学習済みデータのファイル名(ex. ../checkpoints/weights.96-2.83.hdf5)を入れて、24行目の「vid_test.run('~')」の' '内には動画ファイル名を入れます。」
までは行えたのですが、その次の
「以下のような画像が出てくるはずです。」
の部分がわかりません。
なんのプログラムを実行したらそうなるのでしょうか?
投稿: benkyo | 2018年10月17日 (水) 15時44分
こんにちは、benkyoさん。
言われてみれば、抜けてますね。まさに編集中のコードを実行します。
python videotest_example.py
そうすると、物体検出の画像が出てきます。お試しください。
投稿: arkouji | 2018年10月17日 (水) 18時35分
ご返信ありがとうございます。
うまくいきました。
このブログのおかげもあり、これから物体認識についてどんどん取り組んでいこうと思います。
ありがとうございました。
投稿: benkyo | 2018年10月18日 (木) 16時24分
たびたびの質問すみません
画像からの学習が終了し、動画からの検出を行おうと思って上記のように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 | 2018年10月22日 (月) 11時09分
こんにちは、benkyoさん。
うーん、よくわかりませんね。以下のissueがよく似てますけど、こちらもよくわかりませんでした。
https://github.com/rykov8/ssd_keras/issues/136
なんとなくですが、ニューラルネットワークのどこかが崩れちゃったんですかね?でもこのコードでは、そういうのはできない気がしますが。
投稿: arkouji | 2018年10月23日 (火) 18時03分
返信ありがとうございます。
これはpythonやkeras、tensorflow、をインストールしなおしたほうが良いんでしょうか...?
投稿: benkyo | 2018年10月24日 (水) 13時35分
こんにちは、benkyoさん。
そういうレベルのものではないと思います。多分、同じコードを別のPCに持っていっても起こる類のことのように思います。
video_example.pyで読み込ませる学習器を「weights_SSD300.hdf5」に戻しても、同じエラーが出ますか?もし出ないようなら、独自データで学習させて作った学習器(weights_〜.hdf5)がおかしいと分かるので、対処のしようがあるかもしれません。
投稿: arkouji | 2018年10月24日 (水) 16時37分
返信ありがとうございます。
weights_SSD300.hdf5でやってみたものの、やはり同じエラーが出てしまいます。
これは対処が難しいでしょうか?
投稿: benkyo | 2018年10月25日 (木) 11時33分
こんにちは、benkyoさん。
どこかコードをいじってしまってますね。もう一度Githubからオリジナルのコードを持ってきた方が良さそうです。今わかるのは、それくらいでしょうか。
投稿: arkouji | 2018年10月26日 (金) 06時14分
返信ありがとうございます。
この件に関しまして、無事解決しましたのでご報告させていただきます。
エラーの理由はおそらくvideotext_example.pyの中身の
class_name =
以降にある最初の
"background"
を誤って削除したからだと思われます。
お騒がせしてすみませんでした。
投稿: benkyo | 2018年10月26日 (金) 16時32分
こんにちは、benkyoさん。
あ…それでエラーが出てたんですね。なるほど、私も勉強になります。
ところで、今まさに物体検出を会社でトライ中です。このコードも使えないか、検討中。これはこれでよくできたコードなので、便利ですね。
投稿: arkouji | 2018年10月27日 (土) 06時56分
はじめまして。
こちらのブログを参考に動画から物体を検出させたのですが、「SSD_result」のウィンドウを閉じようとしても何回も復活してしまいます。
prompt自体を終了させる以外に、どうしたらSSD_resultのウィンドウを閉じることができるのでしょうか。
投稿: as | 2018年11月19日 (月) 16時34分
こんにちは、asさん。
プロンプトで「Ctrl + C」を押して止まりませんか?おっしゃる通り、画像の方を閉じても、実行コマンドが動き続ける限り復活します。私もしょっちゅう使ってます。多分、それで止まると思います。
投稿: arkouji | 2018年11月20日 (火) 04時42分
返信ありがとうございます。おかげさまで解決しました。
投稿: as | 2018年11月27日 (火) 16時55分
お久しぶりです,、taguseiです。
今回、独自で画像データを大量に用意できたため、もう一度やってみようと思っているのですが
不明な点があったのでもし知っていらっしゃれば教えていただきたいです。
今回、使用する画像の大きさが640×480なのですが、train_ssd_keras.pyのソースコードに
input_shape = (300, 300, 3)
と記述してあるところは変更しないでもよろしいのでしょうか?
投稿: tagusei | 2018年12月11日 (火) 10時07分
こんにちは、taguseiさん。
input_shapeは変えなくていいです。内部で勝手にそのサイズに変えて学習してくれてるようです。
どうしても解像度を変えたい場合、その先のニューラルネットワークも変えないといけなくなるはずです。解像度を上げれば精度が上がるかというとそうとばかりも言えないので、まずはそのまま使ったほうが良さそうです。
投稿: arkouji | 2018年12月12日 (水) 15時28分
返信ありがとうございます。
おっしゃっている通りであれば、画像は640×480の大きさのままで画像の大きさに関してソースコードの記述は変更しなくても大丈夫ということでよろしいでしょうか。
何度もすみません。
投稿: tagusei | 2018年12月13日 (木) 09時56分
はじめまして。突然ですが私は今この記事を参考に独自データをつかって麻雀牌の学習させようとしています。
独自データとそのアノテーションデータを用意し、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のような元からあるファイルとは別に作ったのですがそれが原因なのでしょうか・・・
それともどこか変更するところが足りないのでしょうか?
投稿: undus | 2018年12月13日 (木) 12時40分
すいません解決しましたw
/ssd_keras/VOC2007/の中にフォルダ作って終わりだと思って/ssd_keras/VOCdevkit/の中にも作るのを忘れていたのが原因でした(/ω\)ハズカシー
また詰まった時には相談させていただきますので、その時は是非お願いします(*_ _)人
投稿: undus | 2018年12月13日 (木) 13時23分
独自画像のみを学習させるため、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にして、クラスを一つ増やして実行すると成功しました。
何かヒントなどありますでしょうか。
投稿: 初心者 | 2018年12月20日 (木) 17時58分
とても良い記事ありがとうございます。 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がうまく入らず断念。
投稿: | 2019年1月27日 (日) 09時11分
こんにちは、??さん。
いまいちエラーの内容はわかりませんが、なんとなく必要なライブラリが入ってなさそうな感じのメッセージですね。
もしかしたらですが、python 2.7とtensorflowとkerasの組み合わせがまずいんでしょうかね。
最近、Raspberry Piにtensorflow+kerasの組み合わせを、python 2.7でやろうとしたんですが、頑として動きませんでした。なんとかしてpython3で構築したら、なんとか動くようになりました。
あと、ありがちなのは、tensorflowやkeras、opencvなどを入れているうちに、使っているライブラリが未対応のものが上書きされて、動かなくなるというものでした。エラーの最終行だけをgoogleの検索に入れてググると、対応していないライブラリが出てきて入れなおし……というのを繰り返してました。何度かやってるうちに、うまく行きました。
jetson TX2なら、そのあたりいろいろとノウハウがありそうな気もしますが、実機がないのでよく分かりません。申し訳ないです。
投稿: arkouji | 2019年1月27日 (日) 20時27分
jetson tx2では諦め、 python3(3.6.7)で環境構築し、nvidia xavierで実行できました。
やはりpython3でしか動かないと思います。
環境構築にめっちゃ試行錯誤しました。
投稿: | 2019年2月21日 (木) 15時20分
物体検出を試行するにあたって、非常に参考になりました。
ありがとうございます。
二点ほど、アノテーションについてお尋ねしたいのですが、
1.
>「ImageSets/Main」にある「trainval.txt」に、上で作られた「trainval.txt」の中身を追記します。
こちらは、どういった意図がある作業なのでしょうか。
この部分を行わなくても、当方の環境では学習コードが実行できました。
そのモデルを使い、動画で検出テストした結果も特に問題はないように見えるのですが・・・。
2.
VoTTというアノテーションツールをご存知でしょうか。
それを使って同じように学習コードを実行すると、学習の際にエラーが発生します。
・No such file or directory ...('画像ファイルのパス(なぜか拡張子がついてない?)')
貴殿のアノテーションツールを使えば、1.に記載した通り問題なく学習できており、
xmlファイル生成(アノテーション)以外は同じ手順・構成で実行しています。
また、エラーメッセージが示す画像のパスを確認しても、
しっかりと画像ファイルは存在しているんですよね。
違いといえばxmlの構成ぐらいかなとは思いますが・・・。
何かお気付きの点があればお知恵を頂戴したく、
よろしくお願い申し上げます。
投稿: hoge | 2019年3月 7日 (木) 01時02分
こんにちは、hogeさん。
まず一つ目ですが、get_data_from_XML.pyが「trainval.txt」を読んでいたはず……なのですが、そう言われると自信がないですね。
Pascal VOC 2007形式のデータを使うコードでは、このtrainval.txtを使うコードが多いので、思わずかきこんだかけかもしれません。ちなみに、YOLOあたりだと使っていたはずです。
2つ目ですが、よくわかりませんね……まさかとは思うのですが、改行コードあたりで引っかかるのか、それくらいですね。
とにかく、VOC2007形式のアノテーションをさせたくて無理矢理作ったツールなので、癖はありますが、xmlファイルはちゃんと吐き出すようになっているはずです。実際、うちの業務でも使った実績ありです。もっとも、使いにくいとは言われてますが……
投稿: arkouji | 2019年3月 7日 (木) 16時16分
回答ありがとうございます。
2つ目については解決しました。
VoTTが生成するxmlファイルのタグに、拡張子がつかない仕様であることが原因でした。
つまり「画像」データを参照していなかったんですね。
すべてのxmlファイルを編集して.jpg拡張子を付与したところ、学習が行われました。
1つ目についてはやはりわからないですね。
YOLOは使ったことないのですが、このデータが必要になる旨、認識しておきます。
また何かお気づきになりましたらまた教えていただければ幸いです。
お手数をおかけしました。
投稿: hoge | 2019年3月 8日 (金) 13時21分
1つ目ですが,get_data_from_XML.pyは「VOC2007/Annotations/」フォルダ内の全ファイルを
リストとして受け取ってpklファイルを作成するようになっているようです.
なので,上記フォルダにxmlファイルがあればOKなようです.
逆に,xmlファイル以外のものがあればエラーが出ると思われます.
ただ,私は管理人さんがこの記事でtrainval.txtに言及されていたことで,
YOLOではないですが,別のコードに当たったときに,学習データのロードで
大ハマりせずに済んだので,その節はお世話になりました.
ありがとうございました.
投稿: フニクリフニクラ | 2019年3月 8日 (金) 18時22分
こんにちは、フニクリフニクラさん。
やはりこっちでは不要だったんですね。要るものだという前提で記事を書いてました。ちゃんと調べたほうがいいですね。
ただ、いろいろな物体検出コードを使うときには、とりあえずtrainval.txtは作っといた方がいいのは間違いないですね。
投稿: arkouji | 2019年3月 9日 (土) 19時10分
大変勉強になります。
併せて、基本的なことを教えていただけないでしょうか。
0から学習する?(model.load_weights('weights_SSD300.hdf5', by_name=True)をコメントアウトする)のと、
初期重みにweights_SSD300.hdf5を使う場合では、
後者の方が圧倒的にオブジェクトを検出します。
※まったく新しい物体に対して学習し、検出を試みているのですが、明らかに検出率が違います。
これは所謂、転移学習というものの効果なのでしょうか。
(理想的な重みに近づいた状態で学習をスタートできる、みたいな解釈でよいのでしょうか。)
投稿: hoge | 2019年3月10日 (日) 22時47分
こんにちは、hogeさん。
一見すると余計なデータが入ってしまう転移学習の方が、精度が高いとされてます。特にSSDやYOLOだと、私が試した限りでは転移学習でないとうまくいきませんでした。ゼロからでは、変な局地解に陥っちゃうとでもいうんでしょうか?そんな感じでした。
投稿: arkouji | 2019年3月12日 (火) 06時02分
以下記事とあわせて大変お世話になっています。
https://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程度のカラー画像です。
投稿: とお | 2019年5月 5日 (日) 19時25分
こんにちは、とおさん。返信遅れまして、申し訳ありません。
配列の形状が合わないと言ってるようなので、なんとなくですが、画像ファイルじゃないものを読み込もうとしているようなエラーにも見えます。今言えるのは、それくらいでしょうか?
それくらいしかわかりませんね。すいません。
投稿: arkouji | 2019年5月21日 (火) 10時59分
初めまして
自分でアノテーションしたデータを使って、動画を用いたリアルタイム検出ができないかと色々悩んでいたのですが、記事を参考にさせていただき、とてもわかりやすく簡単に思う通りのこのことができそうです!
ありがとうございます!
投稿: ピーマン | 2019年8月29日 (木) 12時59分
こんにちは、ピーマンさん。
ご活用いただき、ありがとうございます。この記事もちょっと古くなりましたが、未だにアクセス多いです。それだけ、物体検出の需要が多いのだと実感しております。
投稿: arkouji | 2019年8月30日 (金) 07時06分
動画のリアルタイム検出で活用させて頂いています!
お忙しい中、恐縮ですが1点質問させていただきます。
動画のリアルタイム検出で出力したboxの出現個数もリアルタイムでカウントすることなどは可能でしょうか。また、最終的に個数を集計して比率を計算したりなどをイメージしているのですが、、、
可能でしたら、コードの書き方に関してアドバイス頂ければ幸いです。
投稿: ピーマン | 2019年9月 7日 (土) 07時44分