見出し画像

画像処理のあれこれ1 閾値自動選定法の多クラス問題への応用

2020/07/17追記
下記のような情報に見つけたので、実験画像の差し替えを行いました。
https://srad.jp/story/20/07/15/117231/

はじめまして

初めましてアダコテックの伊藤です。製造業に向けた異常検知のAIソフトウェアを提供する㈱アダコテックでエンジニア兼取締役をしています。
エンジニアとしては、コア技術の研究開発、顧客から依頼されたPOCの実施などのを行っています。
仕事以外ではエンジニア仲間と飲みに行ったり、週末は息子と釣りに行ったりしています。(今は、コロナで自粛中ですが・・・)

弊社では、国立研究開発法人産業技術総合研究所(産総研)で発明された高次局所自己相関特徴量(HLAC)(*1)という特徴抽出法を使った異常検出ソリューションの開発・販売を行っております。
この技術を発明された大津展之先生をはじめとした先生方に弊社技術顧問として関わって頂き、毎月の技術定例会議で貴重なアドバイスを頂いております。

画像認識において、事前に画像に対して何らかの画像処理を適用することは認識性能の向上つながる重要な要素です。
本文では、先生方に頂いたアドバイスや業務で実装を試した機能などを「画像処理のあれこれ」と題して紹介したいと思います。(2があるかはわかりませんが)

閾値自動選定の多クラスへの応用

自動閾値選定法(判別分析法)は大津の2値化とも呼ばれ、openCV等にも実装されている非常に有名な手法です。
この手法は入力画像に対して最適な閾値を決定し画像を2値化する事ができ、例えば下記のような感じで画像を2値化する事が可能です。

画像4

しかしながら、輝度値のヒストグラム上で対象が 2 つ以上のクラスタをなし、多クラスで輝度値をクラス分けした方が好ましいケースも考えらえます。
上記の例だと4クラスくらいにわけた方が最適なように見えますが、閾値自動選定法を多クラスに応用する事でN値化画像を生成する事が可能です。(*2)
(note初心者の私には、数式の埋め込み方が解らなかったので別途作成した文書を埋め込みます。)

2クラスの自動閾値選定

画像4

多クラスに応用した場合

画像4

実装してみた

4クラスの自動閾値選定処理をpythonで実装しました。昔、C++で書いたコードをそのままPythonにしたので美しくないかもしれません・・・。)
このプログラムはローカルミニマムを避けるために、グリッドサーチで閾値を決定していますが、クラス数が多くなると処理時間が膨大になるため、別途探査的な最適化手法を導入した方が良いと思います。(8クラスとか、16クラスの自動閾値選定をグリッドサーチで行おうとすると、かなり処理時間が掛かると思います。)

import cv2
import numpy as np
from matplotlib import pyplot as plt

def myThresholdByOtsu4(src):

   #画像サイズの取得 
   height, width = src.shape

   #ヒストグラムの生成 
   hist = np.zeros(256, dtype = 'float32')
   for y in range(height):
       for x in range(width):
           hist[src[y,x]] +=1

   # 閾値自動推定の計算処理
   tableP = np.zeros((256, 256), dtype = 'float32')
   tableS = np.zeros((256, 256), dtype = 'float32')
   tableH = np.zeros((256, 256), dtype = 'float32')

   # 輝度値の分布に対する、2つの累計量(0次、1次の累積モーメント)から、クラス間分散を計算する
   # 輝度#区間[0 i]における0次/1次のモーメント
   for i in range(1,256):
       tableP[i,i] = hist[i]
       tableS[i,i] = i * hist[i]    
   for i in range(1,256 - 1):
       tableP[1,i+1] = tableP[1,i] + hist[i+1]
       tableS[1,i+1] = tableS[1,i] + (i+1) * hist[i+1]
   # 輝度区間[i-1, j]における0次/1次のモーメント
   for i in range(2,256):
       for j in range(i+1,256):
           tableP[i,j] = tableP[1,j] - tableP[1,i-1]
           tableS[i,j] = tableS[1,j] - tableS[1,i-1]

   # ∑w(k)(μ(k)-μ_t)の"w(k)(μ(k)-μ_t)"の部分に該当
   # i,jでクラスkの区間を表現している
   for i in range(1,256):
       for j in range(i,256):
           if tableP[i,j] != 0:
               tableH[i,j] = (tableS[i,j] * tableS[i,j]) / tableP[i,j]
           else:
               tableH[i,j] = 0
   
   # 閾値を決める
   threshold = np.zeros(4, dtype = 'uint8')
   maxSig = 0.0
   for i in range(256-4):
       for j in range(i+1, 256-3):
           for k in range(j+1, 256-2):
               Sq = tableH[1,i] + tableH[i+1,j] + tableH[j+1,k] + tableH[k+1,255];
               if maxSig < Sq:
                   threshold[1]  = i
                   threshold[2]  = j
                   threshold[3]  = k
                   maxSig = Sq
   print (threshold)
   #4値化処理 
   dest = np.zeros((height,width), dtype = 'uint8')
   w =  255 / (4 - 1);
   for y in range(height):
      for x in range(width):
          for t in range(1, 4):
              if src[y,x] < threshold[t]:
                  th = t - 1
                  break
          else:
              th = 4 - 1
          dest[y,x] = w * th
   return dest

この関数を実行した結果はこんな感じです。
情報量が増える事で、2値画像より元の絵の雰囲気が残っています。

画像4

おわりに

かなり説明をはしょりましたが、「閾値自動選定法の多クラス問題への応用」というテーマで本文を記載しました。
このような処理を利用する事で適度に画像内のノイズを除去する事ができ、画像認識の精度を向上させる事が期待できると思います。

参考文献

*1 大津展之「適応学習型汎用認識システム: ARGUS」
*2 大津展之 (2013)  『画像認識の基礎と応用 —  HLAC特徴を用いた学習型汎用認識』 トリケップス .

メンバー募集中です
アダコテックは上記のような画像処理技術を使って、大手メーカーの検査ラインを自動化するソフトウェアを開発している会社です。
機械学習や画像処理の内部ロジックに興味がある方、ご連絡下さい!  
我々と一緒にモノづくりに革新を起こしましょう!
https://adacotech.co.jp/recruit





この記事が気に入ったらサポートをしてみませんか?