Optuna との連携 -- FIE関数のパラメータ自動調整¶
Optuna と連携し、 FIE関数(平均化フィルタとシフトアベレージ⼆値化)のパラメータを ⾃動調整するサンプルコードです。
本サンプルの実行には予め Optuna と pycma をインストールしておく必要があります。 pip コマンドを使用する場合、次のようにインストールしてください。
pip install optuna==1.2.0 cma==2.7.0
処理内容¶
下図のようなノイズとシェーディングのあるチェスボード画像の二値化を考えます。
下図のような出力結果を得ることが理想です。
画像処理手続きは下記の通りとします。
入力画像(図1)読み込み
MxN平均化フィルタ
fnFIE_averageMxN()
による平滑化局所領域平均値とオフセットによる2値化(シフトアベレージ2値化)
fnFIE_shift_avr_threshold_offset()
結果出力
この手続きで使用する下記5種類のパラメータを自動決定します。
MxN平均化 フィルタ横サイズ (ave_x)
MxN平均化 フィルタ縦サイズ (ave_y)
シフトアベレージ2値化 局所領域平均エリア横サイズ (shift_ave_x)
シフトアベレージ2値化 局所領域平均エリア縦サイズ (shift_ave_y)
シフトアベレージ2値化 オフセット値 (shift_ave_offset)
自動決定のための評価基準として、結果画像と理想画像の差の絶対値和を使用します。
コード¶
import pyfie
import optuna
def main():
"""メイン処理"""
# 利便のため、FIE関数のエラーを例外にする
pyfie.ctrl.enable_f_err_exception(True)
# 入力画像読み込み
hsrc = pyfie.imread("optuna_src.png")
# 正解画像(理想の出力画像)読み込み
hans = pyfie.imread("optuna_ans.png")
# パラメータ探索用オブジェクト作成
objective = Objective(hsrc, hans)
sampler = optuna.integration.CmaEsSampler() # サンプリングアルゴリズムはCMA-ES
study = optuna.create_study(sampler=sampler)
# パラメータ探索実行
study.optimize(objective, n_trials=500)
# 結果出力
# 推定されたパラメータを表示
print("推定された最適なパラメータ: ", study.best_params)
# 出力画像を得るため最適なパラメータでもう一度処理
objective(optuna.trial.FixedTrial(study.best_params))
# 出力画像を保存
pyfie.imwrite("optuna_dst.png", objective.hdst)
print("出力画像をoptuna_dst.pngとして保存しました。")
class Objective(object):
"""目的関数クラス"""
def __init__(self, hsrc, hans):
self.hsrc = hsrc # 入力画像
self.hans = hans # 正解画像
# 入力画像はuc8, 1ch. 正解画像はbin, 1ch. 2画像のサイズは等しい
assert hsrc.f_type == pyfie.F_IMG_UC8
assert hans.f_type == pyfie.F_IMG_BIN
assert hsrc.ch == 1 and hans.ch == 1
assert hsrc.width == hans.width and hsrc.height == hans.height
# 作業用画像確保
self.have = hsrc.empty_like()
self.hdiff = hans.empty_like()
# 出力画像確保
self.hdst = hans.empty_like()
def __call__(self, trial):
"""目的関数。画像処理手続き本体を兼ねる"""
# -- 今回試すパラメータを取得
# 平均化フィルタサイズ
ave_x = int(trial.suggest_discrete_uniform('ave_x', 1, 99, 2.0))
ave_y = int(trial.suggest_discrete_uniform('ave_y', 1, 99, 2.0))
# 局所領域平均値とオフセットによる2値化
# 近傍平均エリアサイズ
shift_ave_x = int(trial.suggest_discrete_uniform(
'shift_ave_x', 3, 99, 2.0))
shift_ave_y = int(trial.suggest_discrete_uniform(
'shift_ave_y', 3, 99, 2.0))
# オフセット
shift_ave_offset = trial.suggest_int('shift_ave_offset', -100, +100)
# -- 処理実行
pyfie.fnFIE_averageMxN(
self.hsrc, self.have, ave_x, ave_y, pyfie.F_BORDER_CONTINUOUS, 0
)
pyfie.fnFIE_shift_avr_threshold_offset(
self.have, self.hdst, shift_ave_x, shift_ave_y, shift_ave_offset,
pyfie.F_BORDER_CONTINUOUS, 0
)
# -- 評価値算出
# 評価値は正解との差の絶対値和とする
pyfie.fnFIE_img_diff(self.hdst, self.hans, self.hdiff)
sad = self.hdiff.clone_to_ndarray().sum()
return sad
if __name__ == "__main__":
main()
処理結果例¶
$ python sample_optuna.py
[I 2020-05-27 16:58:56,489] Finished trial#0 resulted in value: 125000.0. Current best value is 125000.0 with parameters: {'ave_x': 97.0, 'ave_y': 23.0, 'shift_ave_x': 41.0, 'shift_ave_y': 11.0, 'shift_ave_offset': -89}.
[I 2020-05-27 16:58:56,573] Finished trial#1 resulted in value: 58870.0. Current best value is 58870.0 with parameters: {'ave_x': 35.0, 'ave_y': 41.0, 'shift_ave_x': 23.0, 'shift_ave_y': 75.0, 'shift_ave_offset': -2}.
[I 2020-05-27 16:58:56,656] Finished trial#2 resulted in value: 125000.0. Current best value is 58870.0 with parameters: {'ave_x': 35.0, 'ave_y': 41.0, 'shift_ave_x': 23.0, 'shift_ave_y': 75.0, 'shift_ave_offset': -2}.
[I 2020-05-27 16:58:56,736] Finished trial#3 resulted in value: 125000.0. Current best value is 58870.0 with parameters: {'ave_x': 35.0, 'ave_y': 41.0, 'shift_ave_x': 23.0, 'shift_ave_y': 75.0, 'shift_ave_offset': -2}.
[I 2020-05-27 16:58:56,819] Finished trial#4 resulted in value: 123599.0. Current best value is 58870.0 with parameters: {'ave_x': 35.0, 'ave_y': 41.0, 'shift_ave_x': 23.0, 'shift_ave_y': 75.0, 'shift_ave_offset': -2}.
... (中略) ...
[I 2020-05-27 17:01:39,949] Finished trial#497 resulted in value: 81.0. Current best value is 80.0 with parameters: {'ave_x': 3.0, 'ave_y': 3.0, 'shift_ave_x': 65.0, 'shift_ave_y': 55.0, 'shift_ave_offset': -1}.
[I 2020-05-27 17:01:40,487] Finished trial#498 resulted in value: 80.0. Current best value is 80.0 with parameters: {'ave_x': 3.0, 'ave_y': 3.0, 'shift_ave_x': 65.0, 'shift_ave_y': 55.0, 'shift_ave_offset': -1}.
[I 2020-05-27 17:01:40,994] Finished trial#499 resulted in value: 81.0. Current best value is 80.0 with parameters: {'ave_x': 3.0, 'ave_y': 3.0, 'shift_ave_x': 65.0, 'shift_ave_y': 55.0, 'shift_ave_offset': -1}.
推定された最適なパラメータ: {'ave_x': 3.0, 'ave_y': 3.0, 'shift_ave_x': 65.0, 'shift_ave_y': 55.0, 'shift_ave_offset': -1}
出力画像をoptuna_dst.pngとして保存しました。
結果画像
注釈
本サンプルコードは単純な評価基準と探索アルゴリズムを用いているため、 処理結果は不安定で低精度であることにご注意ください。