今回の記事はPythonでOpenCV・Kerasなどを用いて機械学習に有効な画像Augmentetion(画像の水増し)の有用なケースなどまとめた記事になっております。
私が機械学習で識別モデルを作成するにあたって「どのようなOpenCV・Kerasの画像水増しメソッド」を「どのような場合」に使用したかを記載していきます。是非参考にしてみてください。
OpenCV と Keras の説明
軽い説明です。
OpenCVとはオープンソースのソフトのようなもので、ネット上にあります。
このOpenCVを直接使用することもできますが意外と設定手順が大変です。
かなり複雑なC言語関連の歴史があるのでgccなどの幾つものライブラリのようなものをコンパイルする必要があります。
正直このあたりはかなりややこしいのでできればさわりたくないです。。。
そういった場合にPythonでOpenCV利用できるモジュールのopencv-pythonがかなり便利なのです。
このモジュールをインストールすればOpenCVのメソッドを普通に使用することができます。
pip でインストールしてください。
pip install opencv-python
仮に追加する必要のあるモジュールがあればエラーを吐いてくれるのでそのモジュールもセットでインストールしてください。
Kerasに関しては機械学習を行う際にかなり楽に、一般人でも行うようにしてくれたPythonライブラリ(pip install で使用できるもの)です。作ってくれた方は神に近いです。
このKerasを用いて分類問題などのAIモデルを作成することができます。
TensorFlowコードは非常に醜いのですが、Kerasは非常に見やすいです。
ただ、TensorFlowの方がやはり万能感は否めませんが簡単な分類問題にの場合はKerasが非常に便利です。
また、errorも少ないし。。
pip install keras
Machine Learning に有用な画像Augumentetion
使用した画像は下記です。
OpenCVを利用した画像処理一覧
あくまでも私が有用と判断したものでまだまだメソッドはありますしきっと有用なものはたくさん眠っていると感じております。
・グレイスケール
・2値化
・アフィン変換
・射影変換
・輝度変化
import cv2
import numpy as np
#画像読み込み
img = cv2.imread("/1002/hatena.jpg")
#リサイズ
img = cv2.resize(img,(100,100))
cv2.imwrite('./result/' + 'hatena_sonomama.jpg' , img)
# グレイスケール化
img_grayscale = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
cv2.imwrite('./result/' + 'hatena_grayscale.jpg' , img_grayscale)
# 二値化
ret,img_2chika = cv2.threshold(img_grayscale,200,255,cv2.THRESH_BINARY)
cv2.imwrite('./result/' + 'hatena_2chika.jpg' , img_2chika)
#アフィン変換(正直よくわかってない。。)
rows,cols,ch = img.shape
pts1 = np.float32([[0,50],[50,0],[10,50]])
pts2 = np.float32([[0,50],[40,10],[10,50]])
M = cv2.getAffineTransform(pts1,pts2)
img_afin = cv2.warpAffine(img,M,(cols,rows))
cv2.imwrite('./result/' + 'hatena_afin.jpg' , img_afin)
#射影変換(上への傾き画像生成)
rows,cols,ch = img.shape
pts1 = np.float32([[0,0],[100,0],[0,100],[100,100]])
pts2 = np.float32([[20,0],[80,0],[0,100],[100,100]])
M = cv2.getPerspectiveTransform(pts1,pts2)
img_syaei = cv2.warpPerspective(img,M,(100,100))
cv2.imwrite('./result/' + 'hatena_syaei.jpg' , img_syaei)
#輝度変化
def gamma_correction(image,gamma):#輝度変化用の関数
lookup_table = np.zeros((256, 1), dtype = 'uint8')
for loop in range(256):
lookup_table[loop][0] = 255 * pow(float(loop)/255, 1.0/gamma)
image_gamma = cv2.LUT(image, lookup_table)
return image_gamma
img_dark = gamma_correction(img,0.1)#暗く
img_light = gamma_correction(img,1.9)#暗く
cv2.imwrite('./result/' + 'hatena_dark.jpg' , img_dark)
cv2.imwrite('./result/' + 'hatena_light.jpg' , img_light)
環境構築に間違っていなければおそらくエラーはないかと。
出ればフォルダを作っていないや画像のパスが間違っているとかですおそらく。
Kerasを利用した画像処理一覧
OpenCVでも可能ですが私はなぜか使い分けてしまっていました。
・水平移動
・垂直移動
・回転
・拡大縮小
・アフィン変換
・左右反転
・上下反転
from tensorflow.keras.preprocessing import image
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
img_path = "/1002/hatena.jpg"
img = image.load_img(img_path)#画像の読み込み
img = np.array(img)
x = img[np.newaxis]
#水平移動
datagen1 = image.ImageDataGenerator(width_shift_range=0.3)#移動0.3
gen1 = datagen1.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches1 = next(gen1) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img1 = batches1[0].astype(np.uint8)
im1 = Image.fromarray(gen_img1)
im1.save('./result/hatena_suihei.jpg')
#垂直移動
datagen2 = image.ImageDataGenerator(height_shift_range=0.2)#移動0.2
gen2 = datagen2.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches2 = next(gen2) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img2 = batches2[0].astype(np.uint8)
im2 = Image.fromarray(gen_img2)
im2.save('./result/hatena_suityoku.jpg')
#回転
datagen3 = image.ImageDataGenerator(rotation_range=20)#角度20
gen3 = datagen3.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches3 = next(gen3) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img3 = batches3[0].astype(np.uint8)
im3 = Image.fromarray(gen_img3)
im3.save('./result/hatena_kaiten.jpg')
#拡大縮小
#縮小
datagen4 = image.ImageDataGenerator(zoom_range=0.1)
gen4 = datagen4.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches4 = next(gen4) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img4 = batches4[0].astype(np.uint8)
im4 = Image.fromarray(gen_img4)
im4.save('./result/hatena_small.jpg')
#拡大
datagen5 = image.ImageDataGenerator(zoom_range=1.9)
gen5 = datagen5.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches5 = next(gen5) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img5 = batches5[0].astype(np.uint8)
im5 = Image.fromarray(gen_img5)
im5.save('./result/hatena_big.jpg')
#アフィン変換
datagen6 = image.ImageDataGenerator(shear_range=40)
gen6 = datagen6.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches6 = next(gen6) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img6 = batches6[0].astype(np.uint8)
im6 = Image.fromarray(gen_img6)
im6.save('./result/hatena_afin.jpg')
#上下反転
datagen7 = image.ImageDataGenerator(vertical_flip=True)
gen7 = datagen7.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches7 = next(gen7) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img7 = batches7[0].astype(np.uint8)
im7 = Image.fromarray(gen_img7)
im7.save('./result/hatena_zyogehanten.jpg')
#左右反転
datagen8 = image.ImageDataGenerator(horizontal_flip=True)
gen8 = datagen8.flow(x, batch_size=1) # 1枚しかないので、ミニバッチ数は1
batches8 = next(gen8) # (NumBatches, Height, Width, Channels) の4次元データを返す。
gen_img8 = batches8[0].astype(np.uint8)
im8 = Image.fromarray(gen_img8)
im8.save('./result/hatena_sayuhanten.jpg')
そのまま 垂直移動 水平移動 回転 縮小 拡大 アフィン変換 左右反転 上下反転
opencvよりは時間かかります。
[]TensorFlowを利用した画像処理補足
正直TensorFlowを利用した画像の水増し処理はおすすめしません。
理由は速度の面です。
TensorFlowで行えることはKerasとOpenCVがあれば可能です。
そのために長い時間を使って処理を行うのはよくないと思います。(夜間や並行処理として行う分にはいいですがAWSなどで行うと費用面も追加されますし。。)
速度面で工夫が必要です。
どのような場面でどのAugumentetionが有用か
文字分類の場合
文字分類の場合は大きな角度の回転や、反転などを行ってしまうしまうと別の文字として学習を行なってしまいます。「6」「9」とか反転二回で一緒の文字になってしまいますからね。。
下記が有用です。
・2値化
・アフィン変換
・射影変換(上を眺めるなど斜め画像をインプットさせる際)
・輝度変化
・水平移動
・垂直移動
・回転(微細角でないと違う文字として学習してしまう。)
・拡大縮小
物体識別の場合
物体識別の場合は画像を好きな角度に回転させても反転させても同じ識別対象なので画像の水増しがかなり楽です。
下記が有用です。
・アフィン変換
・射影変換
・輝度変化
・水平移動
・垂直移動
・回転
・拡大縮小
・アフィン変換
・左右反転
・上下反転
OCR処理を行う場合
OCRの精度が悪いのはともかく入力画像の前処理をやるやらないでは大きく精度に差がでます。
下記が最低限必要です。他にも水平補正できるのであれば行いましょう。
・2値化
以上ですが有用だと断言できるのは私が実際に実装してモデルを作成した上での感想です。異論はもちろん認めますのでコメントください。
コメント
[…] […]
[…] […]
[…] 画像の水増し […]
[…] 「[Python]OpenCV・Kerasの画像の水増し方法まとめ(10手法以上)」 […]