SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ITエンジニアのためのスパースモデリング入門

スパースモデリングの画像処理への発展的な応用~欠損補間、異常検知、超解像

  • X ポスト
  • このエントリーをはてなブックマークに追加

異常検知

 次の例は辞書学習を用いた画像の異常検知についてです。

 異常検知は、画像が正常なのか、異常なのかを判定するという問題で、パターンマッチングを用いる古典的な方法からディープラーニングを使った最新の手法などさまざまなものがありますが、今回は辞書学習を用いた手法を紹介します。

 まず、辞書学習を用いた異常検知についての基本的なアイデアを説明します。学習データとして、何枚かの正常画像を用意しておき、これらから辞書とスパース表現を求めます。このとき、辞書の表現能力を小さくしておくと、学習画像と似た特徴を持つ画像であれば、得られた辞書を組み合わせるだけで再構成できるが、それ以外の画像は辞書を組み合わせるだけでは表現できないという状況が作り出せます。

 そこで、新しい画像に対して得られた辞書のスパース表現を求め、元の画像をうまく再構成できれば正常、そうでないなら異常と判定することで、辞書学習を用いた異常検知を実現することができます。

 それでは、実際に辞書学習で異常検知ができるか試してみましょう。今回は、以下の2枚の木の板の画像を用意しました。

左:木の板の正常画像、右:木の板の異常画像
左:木の板の正常画像、右:木の板の異常画像

 このように、異常画像には6箇所に傷や穴などがあります。正常画像と異常画像で木目のパターンが多少異なるため、単純な差分を用いた異常検知は難しいことがわかります。そこで、木目のパターンをうまく学習することで、異常検知ができるか試してみます。

 まずは、正常画像のみを用いて辞書学習を行います。このとき、得られた辞書は木の木目のパターンのみだけ再構成できるが、それ以外は再構成できないという状況を作り出したいので、辞書のサイズや辞書を組み合わせる数を小さめに設定しておきます。この一連の流れは以下のようになります。

# 正常画像を読み込み
ok_img = np.asarray(Image.open("img/wood-ok.jpg").convert('L'))

# 正常画像は再構成できるようにしたいが、それ以外は再構成できないように、表現力を小さく設定する
patch_size = (16, 16)
n_components = 10
transform_n_nonzero_coefs = 3

# 学習用データの用意
scl = StandardScaler()
patches = extract_simple_patches_2d(ok_img, patch_size)
patches = patches.reshape(-1, np.prod(patch_size)).astype(np.float64)
Y = scl.fit_transform(patches)

# 辞書学習
ksvd = KSVD(n_components=n_components, transform_n_nonzero_coefs=transform_n_nonzero_coefs, max_iter=max_iter)
X = ksvd.fit_transform(Y)
D = ksvd.components_

 こうして得られた辞書\(D\)とスパースコード\(X\)を用いて、正常画像に対する再構成画像を求めると、以下のようになり、正常画像は問題なく再構成できることがわかりました。

正常画像に対する再構成結果
正常画像に対する再構成結果

 では、次に、異常画像に対して、得られた辞書を用いて再構成してみましょう。

# 異常画像を読み込み
ng_img = np.asarray(Image.open("img/wood-ng.jpg").convert('L'))

# 異常画像に対するスパースコードを求める
patches = extract_simple_patches_2d(ng_img, patch_size)
patches = patches.reshape(-1, np.prod(patch_size)).astype(np.float64)
Y = scl.transform(patches)
X = ksvd.transform(Y)

 すると、再構成画像は次のようになりました。

異常画像に対する再構成結果
異常画像に対する再構成結果

 これを見ると、異常画像中の正常な部分に関しては、問題なく再構成ができているのに対し、異常箇所は傷が消えていたり、再構成がうまくできていなかったりすることがわかります。実際、これらの絶対誤差のヒストグラムを描くと以下のようになり、10を閾値として二値化を行うと、以下のような画像を得ることができます。

異常画像に対する再構成誤差のヒストグラム
異常画像に対する再構成誤差のヒストグラム
異常箇所の抽出
異常箇所の抽出

 このように、再構成誤差が極端に大きい部分のみ抽出することで、異常箇所をあぶり出すことができました。正常画像の方は、得られた辞書でうまく表現できているのに対して、異常画像では異常箇所のみが、うまく再構成できていないということがこの結果からわかります。

 一般的に、機械学習で異常検知を行うとき、正常データと異常データの両方を用いて学習を行う必要がありますが、工業製品などでは、正常データは大量に集まるが、十分な数の異常データは集めることが難しいという場合がほとんどです。

 しかし、辞書学習を用いると、正常データのみから何が正常かを定めることができ、正常な状態から逸脱しているものを異常と判定することができるようになるため、大量の異常データを学習のために用意する必要がなくなります。実は、株式会社HACARUS外観検査SPECTROでは、この辞書学習ベースの異常検知アルゴリズムが採用されています。

次のページ
超解像

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
ITエンジニアのためのスパースモデリング入門連載記事一覧

もっと読む

この記事の著者

増井 隆治(株式会社HACARUS)(マスイ リュウジ)

 中学生の頃からプログラミングに興味を持ち、鈴鹿高専で情報学の基礎を学び、その後京都大学に編入し、より高度な数学を学ぶ。大学の実験で仲良くなった大関先生の紹介でハカルスでアルバイトを始める。3年間のアルバイトの後、2019年4月にハカルス初の新卒として入社。データサイエンティストの仕事に邁進している...

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/12433 2020/06/22 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング