t_kahi’s blog

KNIMEやCellProfiler、創薬に関する記事と,日々のメモです

【CellProfiler】Example pipelineで画像解析の基礎を学ぶ③

こんばんは,@PKです.

CellProfilerのExample pipelineを使って画像解析を学ぶ第3回です.

t-kahi.hatenablog.com

前回,IdentifyPrimaryObjectsでAdvanced settingに少し触れて終わりましたので,今回はその内容について少し紹介したいと思います.

Advanced settingについて

まず,IdentifyPrimaryObjects(Nuclei)をAdvanced settingに変更してみます.

f:id:t_kahi:20181231145647p:plain:w400

このようにAdvanced settingに変えると,設定項目がたくさん出てきます.

今回は,このAdvanced settingで行われている処理について自分が学んだことを紹介します.

Threshold Strategy

  • Global : 単一の閾値を用意してオブジェクトと背景を分離する
  • Adaptive : ピクセルごとに閾値を設定する

DNAの染色画像から核オブジェクトを認識する際には「ある閾値」を設定してこれより大きい場合は核オブジェクトしています.
Globalでは単一の閾値を用いてオブジェクトを認識し,バックグランドが均一である場合に適しています.
Adaptiveでは各ピクセルごとに閾値を設定するので,画像の強度の応じて閾値が変わります.特にバックグランドが不均一な場合に適しています.

Thresholding method

以下のようなメソッドを使うことができます.

  • Manual : 0-1の間の特定の値を閾値とする
  • Measurement : 前回の画像測定の結果を閾値として使用する
  • Minimum cross entropy : 交差エントロピーの最小値を使用する
  • RobustBackground : 背景の明るさの平均Aveと標準偏差σを求めて,Ave + (σ x N)を閾値として使用する
  • Otsu : 大津の二値化処理によって閾値を決定する

大きく分けて,閾値は「自動で決める手法」と「手動で決める手法」があります.
手動で決める場合は,染色条件や測定条件が変わると結果が大きく変わってしまう場合があります.
一方で,自動で決める場合は,解析に時間がかかることや,異常な閾値を設定してしまうことがあるようなので,注意したいと思います.

今回は,DefaultでMinimum cross entropyが使用されていました. 交差エントロピーについては,まだ勉強不足で説明できるレベルではないので参考になる記事をいくつか載せます…

雑記: 交差エントロピーって何 - クッキーの日記
交差エントロピーの導出 - いっきに Python に詳しくなるサイト

その他のメソッドも簡単に紹介します.

大津の二値化は有名な手法です.
こちらは,CellProfilerのヘルプではオブジェクトが全体を占める割合が各画像で大きく異なるときに有効だと説明されていました.
以下参考になる記事をいくつか載せます.
OpenCV - 大津の手法/判別分析法 - Pynote
【画像処理】大津の二値化処理の原理・特徴・計算式 | アルゴリズム雑記

また,RobustBackgroundに関しては,バックグラウンドの最小と最大のピクセル強度を除いて,バックグラウンドの蛍光強度の分布がガウス分布に近似すると仮定します.その後,バックの明るさの平均Aveと標準偏差σを求めて,Ave + (σ x N)を閾値として使用します.
この手法は画像の大部分が背景の時や,バックグランドの背景が異なる場合に薬立つそうです. ポイントとして,認識されるオブジェクトは画像の背景のN倍明るくなります(それ以下はオブジェクトとして認識されなくなる)

Threshold smoothing scale

ここでは閾値を設定する前に画像の平滑化処理を行うための設定です. 撮影した画像はノイズなどによってギザギザしたり,オブジェクト内でもムラがあります.
その状態で閾値を設定すると,目的の領域がうまくとれいないことがあります.なので,画像をわざとぼかすことで,うまく閾値を設定するための処理です.
以下参考です.
空間フィルタリングによる平滑化とエッジ検出 | htsuda.net
画像の平滑化 — OpenCV-Python Tutorials 1 documentation

Defaultでは,Threshold smoothing scale は1.3488(σ)になっています. 例えばこの数値を強引に8とかに変えると,以下のように全然オブジェクトの認識ができていません.

f:id:t_kahi:20181231161858p:plain

Threshold collection factor

設定した閾値を調節することができます
0<factor<1.0 : 閾値を下方に設定する(緩くする)
factor=1.0 : 閾値を変化させない
factor>1.0 : 閾値を上方に設定する(厳しくする)

今回は閾値を変化させたくないので1.0になっています.

Lower and upper bounds on threshold

最小および最大許容閾値を設定します(0から1までの数値).
例えば,自動的に計算された閾値値が妥当な範囲外である場合、最小/最大許容閾値が自動で設定した閾値を上書きします.

わかりやすい例としては,画像に細胞などのオブジェクトがいない場合です. この場合でも,自動で閾値を決めるときは,無理やりオブジェクトがあると仮定して値を出してしまうので,擬陽性となることがあります.
ここで,閾値の許容範囲を設定することで,そのような擬陽性を防ぐことができます.

Method to distinguish clumped objects  

接触しているオブジェクトの認識方法です.

  • Intensity : 強度ピークをもとにオブジェクトを分離する
  • Shape : 形をもとにオブジェクトを分離する
  • None : 分離しない

intensityとshapeの違いは以下の図がわかりやすいと思います.
f:id:t_kahi:20181231164450p:plain

Intensityの場合は,オブジェクトのピークで認識するので,画像の平滑化が重要となってきます.
またshapeの場合は,丸いオブジェクトに対して有効です.

Method to draw dividing lines between clumped objects

セグメント化したオブジェクト間に線を引く方法を選択します.

  • Intensity : オブジェクト間の暗い部分を境界線とする
  • Shape : オブジェクト同士で溝ができる部分で境界線を引く
  • Propagate : 周囲のピクセルの情報をもとにオブジェクトを割り当てる
  • None : 設定しない

どの手法が良いかは,テストモードで試して一番自分が望んでいる分離ができているかどうかで決めるのが良いかと思います.
今後,自分でも試してみて追記したいと思います.

Automatically calculate size of smoothing filter for declumping?

自動で平滑化フィルターのサイズを計算するかどうか選択できる.
オブジェクトの分離がうまくできていないときはNoを選ぶ.
値を小さくすることで,よりオブジェクトの分離度を上げることができる.

Automatically calculate minimum allowed distance between local maxima?

オブジェクトの分離がうまくできていないときはNoを選ぶ.
値を小さくすることで,よりオブジェクトの分離度を上げることができる.

Speed up by using lower-resolution image to find local maxima?

オブジェクトの分離をするときに,画像の解像度を下げて極大値を見つけやすくできる.
Yesにすると,画像の処理速度が上がる.

Fill holes in identified objects?

オブジェクトの中に穴が開いている場合に,埋めることができます.

  • After both thresholding and declumping : 閾値の設定後とオブジェクトの分離後に穴を埋める
  • After declumping only : オブジェクトの分離後に穴を埋める
  • Never : 穴は埋めない.

最後に

Advanced settingをポチポチといじって,試しにBasicと比較しました. f:id:t_kahi:20181231174724p:plain:w400

少し核の認識精度が向上しているような気がします(青枠)が,まだ分離できていない核もあります(赤枠)

f:id:t_kahi:20181231174053p:plain

pythonOpenCVを使えるように勉強して,画像解析ができるようになればこの辺の理解も深まるのですが,まだそこまでいけていないです...

Advanced settingはこの程度で終わりにして,次からはpipelineの流れの紹介の続きをやりたいと思います.