Mask R-CNNを使って、自作の粒子画像データ(マスク付きPNG)をCOCO形式で学習・推論する方法をまとめました。
Python+Matterport実装ベースで、Kaggle形式やnucleus.py、coco.pyの応用にも対応しています。
本記事では、「Mask R-CNNを使って粒子レベルのインスタンスセグメンテーションを行う」 というテーマを扱います。具体的には、GitHubの matterport/Mask_RCNN で提供されている nucleps.py を活用し、手軽な1クラス分類(1種類の物体を分類可能)にトライします。
そのあと、COCO形式という独自のフォーマットを利用して coco.py を活用し、同時に多クラス分類することに挑戦します。
自作マスキング画像データセットに対してどのようにCOCO形式Jsonファイルを作成し、学習や推論(推定)まで持ち込むのかを、初心者にも分かりやすい流れで徹底解説してみたいと思います。
「そもそもMask R-CNNって何?」という方から、「論文はちらっと読んだことあるけど、実際どうやって使うの?」という方まで、幅広く楽しめるように構成しています。
§本記事の構成
- Mask R-CNNとは?粒子画像を分割する仕組みと論文の要点
- GitHubのMask_RCNNレポジトリへ:実際のソースコードのポイント
- nucleus.pyに注目:粒子(nuclei)インスタンスセグメンテーションの原理
- COCO形式でマスク画像からJsonを作成する方法(自作データ対応)
- 実際の学習(Fine-Tuning)手順:コマンドやポイントを徹底解説
- 応用展望:他のタスクへの広がり、未来の進化
それでは、さっそく見ていきましょう!
※本記事では論文「Mask R-CNN(arXiv:1703.06870)」及びGitHub「matterport/Mask_RCNN」から図や説明を引用しています。
§0. 画像セグメンテーションとは?
本題に入る前に、画像処理について専門家じゃない方に向けて、そもそもセグメンテーションとかマスクって何?という基礎を、直感的に説明しますね。
「画像セグメンテーション」という言葉を聞いても、ピンとこない人も多いかもしれません。
これは簡単に言えば 「画像の中の特定の部分を切り取る技術」 です。
たとえば、スマホの写真編集アプリで「背景をぼかす」機能を使ったことはありませんか?
あれは、人の部分を 「前景」、その他の部分を 「背景」 に分けることで実現されています。
もう少し具体的に見てみましょう。
画像セグメンテーションのイメージ
👇 下の画像を見てください。 
左側 :元の写真(白い花が背景の前にある)
右側 :花の部分だけを白く、それ以外を黒くした「セグメンテーションマスク」
セグメンテーションマスクとは?
- 白い部分 → 「切り取りたい対象」(この場合は花)
- 黒い部分 → 「それ以外の背景」
こうすることで、たとえば「花だけを抜き出して背景を透明にする」といった画像編集ができるわけです。
マスクの役割とは?
- Photoshopなどで「レイヤーマスク」を使ったことがある人は、それと同じイメージ。
- マスク = どの部分を使うか / どの部分を無視するか を指定するフィルターのようなもの
- 背景を削除する、特定の物体だけ色を変える、AIに「この部分を編集して!」と指示する… などに使える
セグメンテーションと物体検出の違い
よく「物体検出」と「セグメンテーション」は混同されがちですが、ざっくりいうとこんな違いがあります。
| 技術名 | 何をする? | 出力例 |
|---|---|---|
| 物体検出 (Object Detection) | 画像内の特定の物体に「四角い枠(バウンディングボックス)」をつける | 🟥 物体が四角で囲まれる |
| セグメンテーション (Segmentation) | 物体の形状にピッタリ沿ったマスクを作る | 🌿 物体の輪郭が正確に切り取られる |
たとえば、👆の猫の画像なら…
(左)物体検出 → 「この四角の中に猫がいるよ!」
(右)セグメンテーション → 「この猫の形にぴったり沿って切り取るよ!」
画像セグメンテーションは、物体検出よりも 「より細かく形状を捉えられる」 のがポイントです。
1.Mask R-CNNとは?粒子画像を分割する仕組みと論文の要点
1.1 論文の背景
Mask R-CNNは、2017年にKaiming HeらFacebook AI Research (FAIR)の研究チームが発表した 「Object Instance Segmentation」 の手法です。論文タイトルは
"Mask R-CNN" (arXiv:1703.06870)
この論文が目指したのは、「物体を見つけつつ、各物体のピクセル単位マスクを得る」 というタスクの高精度化と高効率化でした。
- 単なるバウンディングボックス(境界矩形)ではなく、対象物の形状(マスク)をピクセルレベルで得たい。
- かつ、画像内の複数オブジェクトを「インスタンス」として識別したい(同じクラスでも個体が複数あるなら、個別にマスクを出したい)。
論文では、Faster R-CNN(2段構成で、高速に物体検出を行う手法)の思想を拡張し、そこに「マスクを予測するブランチ」を並列的に追加する形で、物体領域の推定を実現しています。
1.2 Mask R-CNNの基本構造
ざっくり構造を図示すると、以下のようになります(論文のFigure 1が典型的)。
- Backbone: ResNet101やResNeXtなどの高性能CNNを利用し、画像特徴マップを抽出。
- Region Proposal Network (RPN): 提案領域(RoIと呼ばれる物体候補)を見つける。
- RoIAlign: 提案領域(RoI)に対して、ピクセル単位での特徴切り出しを厳密に行う仕組み。
- Bounding Box Branch: RoIを分類し、バウンディングボックスをさらに精密に回帰(調整)する。
- Mask Branch: それぞれのRoIに対して二次元マスクを推定する。
RoIAlignのポイント
Mask R-CNNが特に強調するのは「RoIAlign」というレイヤーです。
先行手法であるFaster R-CNNはRoIPoolを使うのですが、座標の量子化(プーリング時のずれ) が生じるため、ピクセル単位のマスク精度を下げやすいという欠点がありました。
RoIAlignでは、この量子化を廃し、バイリニア補間 によって微妙な位置まで正確に特徴マップをサンプリングします。
これにより、マスクの境界がより正確に復元 できるという利点があります。
マルチタスク学習
Mask R-CNNは、「分類」+「バウンディングボックス回帰」+「マスク推定」 を同時学習します。
ただし、マスク推定は「各クラスごとに独立なバイナリマスクを予測」させる仕組みを採用。
これは、論文で述べられるように、ピクセルごとにクラスを競合させるsoftmax方法よりも精度が高いとされています。
1.3 成果とインパクト
- COCOデータセットのインスタンスセグメンテーション、物体検出、キーポイント検出 の各競技タスクで、当時のSOTA性能を達成。
- しかも、5fps 程度のリアルタイムに近い速度で動く(ResNet-101を使った場合)というスピードも実現。
- 拡張容易:人体姿勢推定(keypoints)などにも流用しやすく、『インスタンス単位で何かを検出・分割する』 多様な応用に繋がるフレームワークとなった。
論文の考察にあるように、「ピクセル精度が要る場合でも、Faster R-CNNをベースに少し手を加えるだけでうまくいく」発想が、研究コミュニティに大きなインパクトを与えました。
2.GitHubのMask_RCNNレポジトリ:実装の全体像
Mask R-CNNは論文だけでなく、GitHubリポジトリ上に公式実装的なコード も公開されています。
本記事では特に有名な、Matterport社が公開したKeras+TensorFlow実装 matterport/Mask_RCNN を取り上げます。
2.1 matterport/Mask_RCNNの特徴
- ResNet101+Feature Pyramid Network(FPN) をベースとした構成
- MS COCOで事前学習された重み(
mask_rcnn_coco.h5)が提供されており、すぐ試せる - Jupyter Notebookのサンプル が豊富(検出パイプラインの可視化、インスペクションなど)
- マルチGPU 対応のParallelModelクラスなども準備
- 自分のデータセットに合わせた「Datasetクラス」と「Configクラス」を定義するだけで、マスク生成まで実現 できる
- COCOフォーマット対応:COCOデータの学習・評価スクリプトもサンプルに含まれている
2.2 リポジトリ内のファイル構成(主要部分)
model.py,utils.py,config.py: Mask R-CNNのコア実装samples/: いくつかのサンプルデモ・学習スクリプトdemo.ipynb: MS COCOの事前学習モデルを使って、任意画像で物体を検出&マスクするサンプルinspect_data.ipynb,inspect_model.ipynb,inspect_weights.ipynb:各ステップを可視化し、問題をデバッグしやすくするためのノートブック群
3.nucleus.pyをピックアップして解説:粒子インスタンスセグメンテーションの仕組み
mask_rcnnには様々な使い方 がサンプルとして同梱されています。たとえば:
- COCOデータセットの80クラスに対する物体検出・マスク生成
- 風船(balloon)だけをマスクする例
- 幾何図形(shapes)でのトイデータ学習
今回はまず手軽に扱える「nucleus.py」を使い、粒子(nuclei)をセグメンテーション するケースを重点的に見ていきます。
「粒子」と一言でいっても、顕微鏡画像中の細胞核(Nuclei)や、あるいは金属・材料工学での微粒子など様々。
nucleus.pyでは、Kaggleの「Data Science Bowl 2018」(細胞核分割)を想定したスクリプトが用意されており、インスタンスとして多数の「粒子」を一括セグメンテーション する流れがまとまっています。
👆nucleus.pyを使って粒子を認識したイメージ写真です。公式から引用しました。
3.1 nucleus.pyの役割:なぜ粒子のセグメンテーションができる?
nucleus.py の冒頭を眺めると、以下のようなことが書かれています(大意):
""" Mask R-CNN Train on the nuclei segmentation dataset from the Kaggle 2018 Data Science Bowl ... Usage: python3 nucleus.py train --dataset=/path/to/dataset --subset=train --weights=imagenet python3 nucleus.py detect --dataset=/path/to/dataset --subset=train --weights=/path/to/weights.h5 """
- つまり、Kaggleの細胞核データをもとに学習・推論を行うスクリプト
NucleusConfigクラスとNucleusDatasetクラスが定義されており、自作データセットを読み込む時の処理が具体的 に書かれている
NucleusConfig
- “粒子(nucleus)”を1クラス追加 する形で、
NUM_CLASSES = 1 + 1となっている(背景クラス+核クラスの合計2クラス) - 入力画像サイズやアンカーサイズ、ミニマスク(使うかどうか)など、Mask R-CNN特有のパラメータが最適化済み
NucleusDataset
- マスク画像(白黒png)を探し、それぞれのピクセルを「核オブジェクト」として認識している
- 画像ごとに複数マスクがあれば、それらをスタック してマルチインスタンスとして読み込む
- 1つのpngマスクが1インスタンスを意味するため、「どこがどの粒子か」が個別に区別されて学習可能
3.2 「単一クラス×多数インスタンス」への対応
COCOのように80クラスある場合にはNUM_CLASSES = 81(背景を含む)としますが、nucleus.pyでは1クラス(粒子)しかない のでクラス数は2(背景+1クラス)になっています。
ただし、複数個の粒子が画面に散在 しているとき、Mask R-CNNはクラスは同じでもインスタンスごとに別々のマスク を出力できる仕組みがあるため、「同じ粒子クラスが多数ある画像」を同時分割 できるわけです。
3.3 実際にnucleus.pyを使ってセグメンテーションAIをFine-Tuningしてみましょう!
👇nucleus.pyをFine-Tuningするには、下記のフォルダ構成をカスタムデータセットで作成します。
フォルダ構造例(Kaggle細胞核形式)
my_nucleus_dataset/ ├─ stage1_train/ │ ├─ 0001/ │ │ ├─ images/0001.png │ │ └─ masks/... │ ├─ 0002/ │ │ ├─ images/0002.png │ │ └─ masks/... │ ... ├─ stage1_test/ │ ├─ ... └─ ...
- 1つのディレクトリ内に、「元画像ファイル(images/xxx.png)」と、「インスタンスマスクが複数枚(masks/*.png)」という形。
- マスクPNGは、各粒子ごとに白で塗った2値画像 として分割されており、1粒子1ファイル。
もちろん、自前のマスキング画像 さえ同様に準備しておけば、この nucleus.py の枠組みを流用できます。
3.4 データセットクラスとマスク読み込み
nucleus.py の NucleusDataset クラスでは、以下のようにPNGマスクを複数枚重ねて1画像のインスタンス全体を生成します。
class NucleusDataset(utils.Dataset): def load_nucleus(self, dataset_dir, subset): self.add_class("nucleus", 1, "nucleus") ... # subsetが"train"か"val"かでフォルダを切り替え # 画像フォルダを走査してself.add_image(...) def load_mask(self, image_id): # mask_dir = ... # (例) /.../masks/ # PNGファイルを読み込み、粒子ごとに二値配列へ mask = [] for f in mask_files: m = skimage.io.imread(f).astype(np.bool) mask.append(m) mask = np.stack(mask, axis=-1) # すべて「粒子クラス1」で統一 return mask, np.ones([mask.shape[-1]], dtype=np.int32)
これがポイント:
- 1粒子 = 1枚のPNGに白で塗られているので、それをスタック(
np.stack)していくと、[height, width, instance数] の3次元配列ができる。 - 各インスタンスのクラスIDは「1(nucleus)」のみ。
3.5 学習・推論の実行:コマンドライン
nucleus.py は、次のようなコマンドで動かします。
# 学習モード (ImageNet重みを初期値に) python3 nucleus.py train \ --dataset /path/to/my_nucleus_dataset \ --subset train \ --weights=imagenet # あるいはCOCO重みを使うなら python3 nucleus.py train \ --dataset /path/to/my_nucleus_dataset \ --subset train \ --weights=coco # 学習再開 (最後に保存されたweightを読み込む) python3 nucleus.py train \ --dataset /path/to/my_nucleus_dataset \ --subset train \ --weights=last # 推論モード: 学習済み重みで粒子マスクを生成 python nucleus.py detect \ --dataset /path/to/my_nucleus_dataset \ --subset val \ --weights=/path/to/mask_rcnn_nucleus_00xx.h5
学習の流れ (train() 関数)
def train(model, dataset_dir, subset): dataset_train = NucleusDataset() dataset_train.load_nucleus(dataset_dir, subset="train") dataset_train.prepare() dataset_val = NucleusDataset() dataset_val.load_nucleus(dataset_dir, subset="val") dataset_val.prepare() # Augmentationなど設定 augmentation = iaa.SomeOf((0, 2), [...]) # 頭(クラス分類やマスク生成など上位層)のみ学習 model.train(dataset_train, dataset_val, learning_rate=config.LEARNING_RATE, epochs=20, layers='heads') # 全層を学習 model.train(dataset_train, dataset_val, learning_rate=config.LEARNING_RATE, epochs=40, layers='all')
最初はヘッド層だけ、次に全層という2段階で微調整(Fine-Tuning)します。
実際にはエポック数やAugmentationなどを好みに合わせて変更してください。
推論の流れ (detect() 関数)
def detect(model, dataset_dir, subset): dataset = NucleusDataset() dataset.load_nucleus(dataset_dir, subset) dataset.prepare() for image_id in dataset.image_ids: image = dataset.load_image(image_id) result = model.detect([image], verbose=0)[0] # r["rois"], r["masks"], r["class_ids"], r["scores"] ... # ここで推定結果が得られる # さらに可視化 or RLE出力 etc.
推定された各粒子の位置が masks として出力されるので、粒子ごとに個別のマスク が取り出せます。
実際にFine-Tuningした所感として、1クラス検知に特化した調整がされているのか、例えばUnetなど他のセグメンテーションAIと比較しても高精度なマスキングが可能な印象でした。
4.COCO形式でマスク画像からJsonを作成する方法(自作データ対応)
さて、nucleus.pyを使って1クラスをマスキング出来るようになりましたが、実際のタスクでは同時に多クラス分類をしたいという場面も多いでしょう。
その時こそ、多クラス分離が可能な、coco.pyを用いたインスタンスセグメンテーションの出番です。
ここからは、coco.pyを使って多クラス分類が可能なインスタンスセグメンテーションAIをFine-Tuningするハウツーを説明いたしますね。
4.0 はじめに
インスタンスセグメンテーションを実施する時は、COCO形式(Json)と呼ばれるフォーマットを用いることが多いです。
Jsonファイルとは、ざっくり言うと、AIモデルに与える「教科書」の情報を数値データとして詰め込んだ設定ファイルのようなイメージです。
COCO形式のJsonファイルを作成するためには、下記の2点データが必要です。
(例)
Matterport版Mask_RCNN は、COCO形式(Json) に対応しています。
「COCO形式って何?」 という方は、マイクロソフトの論文 “Microsoft COCO: Common Objects in Context” から始まった物体認識用アノテーションの標準フォーマットと思えばOK。
「images」「annotations」「categories」などの構造をもつJsonファイルに、各画像に含まれるインスタンスのピクセル領域を格納し、使い回しがしやすい 大規模データセット形式です。
4.1 マスキング画像からCOCO形式Jsonを作る方法
マスキングした画像から、COCO形式のJsonファイルを自動作成するコードは、下記の記事の最後の方に記述しているのでご参考ください。
👆の記事に記載の、「マスキング画像を見て輪郭を抽出→COCO形式でJson書き出し」 という流れの Pythonコードを用いれば、自前で撮影・作成したデータから比較的簡単にJsonを生成できます。
COCO形式のJsonファイルを作れるかどうかでcoco.pyをFine-Tuningできるかどうか変わってくるので、閲覧推奨です。
- マスキング画像フォルダ: 例えば “mask/class_name/” の下に、各画像IDに対応するpngマスクを用意
- 元画像フォルダ: 例えば “images/” の下に、対応するjpgやpng画像を置いておく
- スクリプトを実行して、COCO構造の“annotations/instances_train2017.json”のようなJsonを作る
- train2017/val2017などに分割 してデータを用意(学習用・検証用)
こうして得られたCOCO形式データセットを、Mask R-CNNに読み込ませる ことで、粒子インスタンスを検出・マスク生成できるようになります。
COCO形式Jsonのポイント
images: 画像ごとのid、file_name、width,heightなどannotations: 各インスタンスのsegmentation(ポリゴン点列やRLE),bbox,category_id,image_idなどcategories: カテゴリ情報(今回なら1カテゴリnucleusだけ)
👆のように、画像のアノテーション情報が数値データとして格納されています。
5.coco.pyの学習(Fine-Tuning)手順:コマンドやポイントを徹底解説
では、coco.pyを使って粒子向けのインスタンスセグメンテーションモデルを学習 するまでを、具体的にステップで示します。
5.0 準備:必要なもの
- Python3, TensorFlow, Keras などの環境(matterport/Mask_RCNNの
requirements.txtを参照) - Mask_RCNNリポジトリのクローン
bash git clone https://github.com/matterport/Mask_RCNN.git - 事前学習ウェイト
mask_rcnn_coco.h5(リポジトリのReleaseページから入手可)- もしくは
imagenet初期化で学習を始めてもよいが、COCOでpretrainした重み があると収束が速い
- もしくは
- 自作データセット
- ファイル構造例:
/path/to/dataset/ ├─ train2017/ ...(train用の画像データ) ├─ val2017/ ...(val用の画像データ) └─ annotations/ ├─ instances_train2017.json └─ instances_val2017.json - あるいはKaggle Data Science Bowlのデータ形式
- ファイル構造例:
5.1 CocoConfig でクラス数を調整する
coco.py には以下のように CocoConfig が定義されています。(一部抜粋)
class CocoConfig(Config): """Configuration for training on MS COCO.""" NAME = "coco" IMAGES_PER_GPU = 2 # ここが重要: COCOは 1 + 80 クラス (背景 + 80) NUM_CLASSES = 1 + 80
自作のCOCO形式データセットが、背景を除いて X クラスある場合、NUM_CLASSES = 1 + X に書き換えてください。
たとえばクラスが5種類(cat, dog, bird, car, bike)なら、こうなります:
class MyCocoConfig(Config): NAME = "my_coco" IMAGES_PER_GPU = 2 NUM_CLASSES = 1 + 5 # 背景 + 5クラス # あとは適宜パラメータを調整
あとは model.py や utils.py などの他ファイルは、matterport/Mask_RCNN 側のままでもOKです。
5.2 コマンドの基本
coco.pyは以下のようにコマンドラインで実行します:
# 新規学習 (COCO重みを使う) python coco.py train --dataset=/path/to/dataset --subset=train --weights=coco # 新規学習 (ImageNet重みを使う) python coco.py train --dataset=/path/to/dataset --subset=train --weights=imagenet # 途中で中断した学習の続き (last) python coco.py train --dataset=/path/to/dataset --subset=train --weights=last # 推論モード (検出・マスク生成) python coco.py detect --dataset=/path/to/dataset --subset=val --weights=/path/to/weights.h5
👆コマンドラインにおいて、 pythonで動かなかったら、python3 を試してみてください。この辺り環境によって違ってきますので。
筆者はいつも、 python で動かしています。
trainコマンドの詳細
--dataset=/path/to/dataset: データセットのルートパス--subset=train: datasetの下にある「train」サブフォルダや「train.json」などを読み込む指定--weights=coco: COCOで学習済みウェイトを初期値にするimagenetやlastや、実際のファイルパス.h5も指定可能
スクリプトの中を見ると、train() 関数で最初に"heads"だけ学習→その後"all"層を学習という2段階学習をしている例が掲載されています。
Heads層とは?
- ResNetなどのbackbone(下層部)は凍結し、RPNや分類・マスク生成などの上位層を先に学習 するやり方
- 大規模データセット(COCO)でpretrainされているため、backboneをすぐには書き換えずに、まずはheads層だけfine-tuneする
学習が安定したら、「all」層 も含めて全体を微調整する流れが推奨されています。
5.3 学習データのパス指定方法
--dataset には、自作のCOCO形式フォルダへのパスを設定します。--model は重みの指定で、coco と書くとMatterportが公開している mask_rcnn_coco.h5 が自動的に読み込まれます(事前にダウンロード必要)。
COCO形式のJsonを読み込む仕組み
class CocoDataset(utils.Dataset): def load_coco(self, dataset_dir, subset, year=2014, ...): ... # annotations/instances_{subset}{year}.json を読み込む coco = COCO("{}/annotations/instances_{}{}.json".format(dataset_dir, subset, year)) ... self.add_class("coco", i, coco.loadCats(i)[0]["name"]) ... self.add_image("coco", image_id=i, path=..., annotations=...) ...
上記のようにpycocotoolsを使って、Jsonファイルから annotations を取り出しているので、標準的なCOCOフォーマット であれば何もしなくても OK。
年号は 2014 か 2017 を想定していますが、自作の場合は subset=train2017, subset=val2017 など好きなフォルダ名で合わせれば大丈夫です。
👆これは好みの問題ですが、筆者は「出来るだけ新しい方が良さそう!」とはじめに思い、以降ずっと2017を使用しています。😂
結果として、複数クラス(例えば cat, dog, bird, ...)を一度に学習&インスタンスセグメンテーションが可能になります。
5.4 学習が完了すると…
学習が進むと、DEFAULT_LOGS_DIR(デフォルトはMask_RCNN/logs/)にエポックごとの学習済みウェイトが.h5ファイルとして保存されます。
例えば
mask_rcnn_nucleus_0001.h5 mask_rcnn_nucleus_0002.h5 ...
のようにエポック番号が付いた重みファイルが作られます。
その中で性能が良いものを、本番推論に使うのが一般的です。(もしくは最後のlastを使う)
5.5 推論(Detectモード)でセグメンテーション結果を得る
学習が一段落したら、今度は detect コマンドを試しましょう。例えば:
python coco.py detect \ --dataset=/path/to/dataset \ --subset=val \ --weights=/path/to/mask_rcnn_coco_0120.h5
- これにより、対応する画像に対して粒子マスク推定 が実行され、
coco.pyのdetect()関数でマスクを合成した画像などが出力されます。 - コードを見ると、RLE(Run Length Encoding) での出力なども実装されており、Kaggleの提出形式 に合わせてCSVを作る処理が書かれています。
こうしたRLE出力は、COCO形式のアノテーション でもしばしば使われる手法で、マスク領域を圧縮して表す 時に便利。
6.応用展望:他のタスクへの広がり、未来の進化
6.1 Mask R-CNNの汎用性
先ほど触れたように、Mask R-CNNは“インスタンス単位で領域を切り分けたい” 場面に幅広く応用可能 です。
「1つのクラスで粒子を区別したい」 でも「複数クラスを同時に分割したい」 でも、同じMask R-CNNの流れを踏襲できるのが大きなメリットといえます。
6.2 未来の展望:さらなる高精度化と新しいパラダイム
- パノプティックセグメンテーション:背景(stuff)も含めてすべてのピクセルをラベルづけ
- 多クラスのインスタンスを一度に区別(しつつ超小さなオブジェクトも見逃さない)
- 3D空間への発展(点群や3Dボクセルを扱うMask R-CNNの派生手法)
- 大規模モデルへの適用(Swin Transformerなどのバックボーンと合わせてさらに高精度化)
ここ数年でセグメンテーション技術は急激に進化しており、Segment Anything Model (SAM) のようにゼロショットで何でもセグメントする、という大きな動きも登場しています。
しかし、特定ドメインの粒子分割などは、まだまだMask R-CNN系の「教師ありインスタンスセグメンテーション」が有力 です。
例えば細かい粒子をしっかり検出してくれる等、実用の場面は多いでしょう。
yuzukaki-chemical.hateblo.jp yuzukaki-chemical.hateblo.jp
👆SAM系統の汎用基盤モデルに焦点を当てた記事も用意してあります!
最新のモデルにも興味のある方はぜひご覧ください。
まとめ:Mask R-CNNで物体(インスタンス)を自由自在に分割しよう!
ここまでのポイントをまとめると、以下のようになります。
-
Mask R-CNNとは
-
matterport/Mask_RCNNリポジトリの構造
nucleus.pyやcoco.pyなど用途別サンプルが用意されている- コア部分は
model.py,config.py,utils.py
-
nucleus.pyの活用
-
COCO形式Jsonとの連携
-
Fine-Tuningの流れ
python coco.py train --dataset=... --weights=coco- 最初はheads層のみ→慣れてきたらall層の微調整
- 学習終了後は
detectモードで推論&可視化
-
今後の展望
- Instance Segmentationは様々な応用が可能
- 大規模モデルとの組み合わせや3D展開なども期待される
おわりに
「Mask R-CNNを使って粒子(nuclei)をインスタンス分割するには?」 というテーマで解説してきました。
- 「セグメンテーションって難しそう…」 と思われがちですが、Mask R-CNNを活用すれば、比較的簡単に一枚の画像に写る複数粒子を一挙に分割できます。
- GitHubの
nucleus.py及びcoco.pyを少し読み解くだけで、自作データの粒子解析にも応用できる のが大きな魅力です。 - 加えて、COCO形式のJsonデータ を用意すると、より一般的なワークフロー(pycocotoolsの活用など)が組みやすくなります。
もし今後、さらに大量の粒子データセットを扱ったり、新しいバックボーン(Swin TransformerやConvNeXtなど)を組み合わせたい場合も、Mask R-CNNの設計は拡張しやすいので、ぜひ色々試してみてください。
Mask R-CNNは2025年現在では古典的な手法になりつつありますが、当時セグメンテーションAI界隈に与えた衝撃は非常に大きく、その軽量さに対する性能の高さは現在でも最新AIに引けを取らないです。
というわけで今回は、初心者の方にもなるべくイメージしやすく、かつ技術的にも奥行きを感じられるように、論文+GitHubリポジトリの視点から Mask R-CNNの粒子インスタンスセグメンテーション をまとめてみました。
最後までお読みいただきありがとうございました!
🔑この記事のポイントまとめ
- Mask R-CNN:Faster R-CNNに「マスク予測ブランチ」を追加し、RoIAlignでピクセル精度を高めたインスタンスセグメンテーション手法
- matterport/Mask_RCNN:Keras/TensorFlow実装を公開。
nucleus.pyなど用途別サンプルが充実していて、自作データ対応が簡単 - nucleus.py:単一クラス(背景+粒子)設定で、顕微鏡下の粒子などを簡単に大量分割できる例を提供
- COCO形式Json:独自のマスク画像データをCOCOフォーマットに変換すると、Mask R-CNNでの学習・推論がスムーズ
- Fine-Tuning手順:
python nucleus.py train/detectコマンドを使うだけ。weightsにcocoを指定すると学習済みモデルを継承できる
参考文献・関連リンク
- Mask R-CNN 論文
- Matterport/Mask_RCNN GitHub
- Microsoft COCO
- https://arxiv.org/abs/1405.0312 (COCO論文)
- https://cocodataset.org (公式サイト)
- Kaggle Data Science Bowl 2018
ライセンス表記:
本記事におけるスクリーンショットはMetaの公開論文からの引用です。
Courtesy of Meta AI (CC BY-NC-ND 4.0)
