----------【2017.09.29】更新には 7 種類のデータ拡張方法のコードが含まれています ----------------------------------------
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
"""
作成日: 2017年9月29日金曜日 15:42:18
@author: hans
http://blog.csdn.net/renhanchi
"""
import skimage
import skimage.io
import numpy as np
import matplotlib.pyplot as plt
import os
import argparse
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
num = 0
def flip(image):
return np.fliplr(image)
def channel_shift(x, limit=0.1, channel_axis=2):
x = np.rollaxis(x, channel_axis, 0)
min_x, max_x = np.min(x), np.max(x)
channel_images = [np.clip(x_ch + np.random.uniform(-limit, limit), min_x, max_x) for x_ch in x]
x = np.stack(channel_images, axis=0)
x = np.rollaxis(x, 0, channel_axis + 1)
return x
def gray(img):
coef = np.array([[[0.114, 0.587, 0.299]]])
gray = np.sum(img * coef, axis=2)
img = np.dstack((gray, gray, gray))
return img
def contrast(img, limit=0.3):
alpha = 1.0 + np.random.uniform(-limit, limit)
coef = np.array([[[0.114, 0.587, 0.299]]])
gray = img * coef
gray = (3.0 * (1.0 - alpha) / gray.size) * np.sum(gray)
img = alpha * img + gray
img = np.clip(img, 0., 1.)
return img
def lighter(img):
return skimage.exposure.adjust_gamma(img, 0.5)
def darker(img):
return skimage.exposure.adjust_gamma(img, 2)
def saturation(img, limit=0.3):
alpha = 1.0 + np.random.uniform(-limit, limit)
coef = np.array([[[0.114, 0.587, 0.299]]])
gray = img * coef
gray = np.sum(gray, axis=2, keepdims=True)
img = alpha * img + (1. - alpha) * gray
img = np.clip(img, 0., 1.)
return img
parser = argparse.ArgumentParser()
parser.add_argument(
'n',
type = str,
help = """\
ディレクトリ名
"""
)
parser.add_argument(
'm',
type = str,
default = 'flip',
help = """\
モード:
flip(img),
channel_shift(img, limit=0.1, channel_axis=2),
gray(img),
contrast(img, limit=0.3),
lighter(img),
darker(img),
saturation(img, limit=0.3)
"""
)
FLAGS = parser.parse_args()
mode = FLAGS.m
cla = FLAGS.n
dirpath = r'%s/' %cla
for dirname in os.listdir(dirpath):
if os.path.isdir(r'%s%s' %(dirpath, dirname)): #ディレクトリかどうかを確認
if not os.path.exists(r'%s_%s/%s/' %(cla, mode, dirname)): #ミラーリングディレクトリが存在するか確認
os.makedirs(r'%s_%s/%s/' %(cla, mode, dirname)) #存在しなければ新しいディレクトリを作成
for imagename in os.listdir(r'%s%s'%(dirpath, dirname)):
num += 1
print '%s saving %s_%s/%s/%s' %(num, cla, mode, dirname, imagename)
image = os.path.join('%s%s/%s' % (dirpath, dirname, imagename))
ori_Image = skimage.img_as_float(skimage.io.imread(image)).astype(np.float64)
if mode == 'flip':
transform_image = flip(ori_Image)
elif mode == 'channel_shift':
transform_image = channel_shift(ori_Image)
elif mode == 'gray':
transform_image = gray(ori_Image)
elif mode == 'contrast':
transform_image = contrast(ori_Image)
elif mode == 'lighter':
transform_image = lighter(ori_Image)
elif mode == 'darker':
transform_image = darker(ori_Image)
elif mode == 'saturation':
transform_image = saturation(ori_Image)
plt.imsave('%s_%s/%s/%s' %(cla, mode, dirname, imagename), transform_image, format='JPEG')
最初の引数はディレクトリ名で、記号はなく、ただのディレクトリ名です。二番目の引数はデータ拡張モード名で、他の内容はなく、ただのモード名です。
時々、トレーニングセットが少なすぎて、すぐに過学習してしまいます。
トレーニングセットを増やすことは必要です。
ディレクトリ構造:
現在のディレクトリ: flower, Mirror.py など
flower/ : 様々な種類の花のディレクトリ
様々な種類の花のディレクトリ / : 現在の種類の花のすべての画像
実行後、現在のディレクトリに新しいディレクトリを作成して新しいデータを保存します
1. 画像のミラーリング#
この方法は使用するかどうかは個人の選択によります。なぜなら、caffe データ層の前処理方法にはミラーリングのスイッチがあり、このスイッチは現在のバッチ画像をランダムにミラーリングします。
layer {
name: "data"
type: "Data"
top: "data"
top: "label"
include {
phase: TRAIN
}
transform_param {
crop_size: 227
mean_file: ".binaryproto"
mirror: true #これがデータをランダムにミラーリングする前処理のスイッチです。
}
data_param {
source: "train_lmdb_227"
batch_size: 64
backend: LMDB
}
コードはやはり公開する必要があります。
#!/usr/bin/env python2
"""
作成日: 2017年7月21日金曜日 11:08:23
@author: hans
"""
import skimage
import skimage.io
import numpy as np
import matplotlib.pyplot as plt
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8') #ubuntuシステム、windowsではgbkを使用
cla = 'vegetable'
dirpath = r'%s/' %cla
for dirname in os.listdir(dirpath):
if os.path.isdir(r'%s%s' %(dirpath, dirname)): #ディレクトリかどうかを確認
if not os.path.exists(r'%s_mirror/%s/' %(cla, dirname)): #ミラーリングディレクトリが存在するか確認
os.makedirs(r'%s_mirror/%s/' %(cla, dirname)) #存在しなければ新しいディレクトリを作成
print "ディレクトリを作成: %s" %dirname
for imagename in os.listdir(r'%s%s'%(dirpath, dirname)):
image = os.path.join('%s%s/%s' % (dirpath, dirname, imagename))
oriMirror = skimage.img_as_float(skimage.io.imread(image)).astype(np.float64)
imgMirror = np.fliplr(oriMirror)
plt.imsave('%s_mirror/%s/%s' %(cla, dirname, imagename), imgMirror, format='JPEG')
2. 明るさの変更#
#!/usr/bin/env python2
"""
作成日: 2017年7月21日金曜日 11:08:23
@author: hans
"""
import skimage
import skimage.io
import matplotlib.pyplot as plt
import numpy as np
import os
import sys
reload(sys)
sys.setdefaultencoding('utf-8')
cla = 'animal'
mode = 'lighter'
dirpath = r'%s/' %cla
for dirname in os.listdir(dirpath):
if os.path.isdir(r'%s%s' %(dirpath, dirname)):
if not os.path.exists(r'%s_%s/%s/' %(cla, mode, dirname)):
os.makedirs(r'%s_%s/%s/' %(cla, mode, dirname))
for imagename in os.listdir(r'%s%s'%(dirpath, dirname)):
print 'saving %s_%s/%s/%s' %(cla, mode, dirname, imagename)
image = os.path.join('%s%s/%s' % (dirpath, dirname, imagename))
ori = skimage.img_as_float(skimage.io.imread(image)).astype(np.float32)
img = skimage.exposure.adjust_gamma(ori, 0.5) # 1未満は明るく、1より大きいと暗くなります。上記のモードと一致させてください。
plt.imsave('%s_%s/%s/%s' %(cla, mode, dirname, imagename), img, format='JPEG')
未完待続...
パススクリプト#
データ名、データタイプインデックス、および現在のディレクトリからそのデータへのパスを.txt に保存し、ランダムに並べ替えます。
#!/bin/sh
classes=(Anthurium asparagus_fern bamboo_palm Begonia cactus cape_jasmine Carnation Cherry_plum chrysanthemum)
for cla in flower flower_mirror
do
num=0 #クラスインデックス
for class in ${classes[@]}
do
ls $cla/$class/* > $class.txt
sed -i "s/$/ $num/g" $class.txt #末尾にクラスインデックスを追加
let num+=1
cat $class.txt >> temp.txt
rm $class.txt
done
done
cat temp.txt | awk 'BEGIN{srand()}{print rand()"\t"$0}' | sort -k1,1 -n | cut -f2- > flower_train.txt #ランダムに並べ替え
rm temp.txt