Main Content

このページの翻訳は最新ではありません。ここをクリックして、英語の最新版を参照してください。

Mask R-CNN を使用したインスタンス セグメンテーションの実行

この例では、マルチクラスの Mask R-CNN (Region-based Convolutional Neural Network) を使用して、人と自動車の個々のインスタンスをセグメント化する方法を説明します。

インスタンス セグメンテーションは、オブジェクトを検出して位置を推定すると同時に、検出された各インスタンスのセグメンテーション マップを生成するコンピューター ビジョン技術です。

この例では、最初に、2 つのクラスを検出する事前学習済みの Mask R-CNN を使用してインスタンスのセグメンテーションを実行する方法を示します。オプションで、データ セットをダウンロードし、転移学習を使用してマルチクラス Mask R-CNN に学習させることもできます。

メモ: この例では、Computer Vision Toolbox™ Model for Mask R-CNN が必要です。Computer Vision Toolbox Model for Mask R-CNN はアドオン エクスプローラーからインストールできます。アドオンのインストールの詳細については、アドオンの取得と管理を参照してください。

事前学習済みの Mask R-CNN を使用したインスタンス セグメンテーションの実行

事前学習済みの Mask R-CNN をダウンロードします。ネットワークはmaskrcnnオブジェクトとして保存されます。

dataFolder = fullfile(tempdir,"coco");
trainedMaskRCNN_url = 'https://www.mathworks.com/supportfiles/vision/data/maskrcnn_object_person_car.mat';
helper.downloadTrainedMaskRCNN(trainedMaskRCNN_url,dataFolder);
Pretrained MaskRCNN network already exists.
pretrained = load(fullfile(dataFolder,'maskrcnn_object_person_car.mat'));
net = pretrained.net;

ターゲット クラスのオブジェクトを含むテスト イメージを読み取ります。

imTest = imread('visionteam.jpg');

関数segmentObjectsを使用して、オブジェクトとそのマスクをセグメント化します。関数 segmentObjects は、予測を実行する前に、入力イメージに対して次の前処理手順を実行します。

  1. COCO データ セット平均を使用してイメージをゼロ センタリングします。

  2. 縦横比 (レター ボックス) を維持したまま、イメージのサイズをネットワークの入力サイズに変更します。

[masks,labels,scores,boxes] = segmentObjects(net,imTest);

関数insertObjectMaskを使用し、検出されたマスクをイメージに重ね合わせて、予測を可視化します。

overlayedImage = insertObjectMask(imTest,masks);
imshow(overlayedImage)

オブジェクトの境界ボックスとラベルを表示します。

showShape("rectangle",gather(boxes),"Label",labels,"LineColor",'r')

学習データのダウンロード

COCO 2014 学習イメージ データ セット [2] は、82,783 個のイメージで構成されています。注釈データには、各イメージごとに最低 5 つの対応するキャプションが格納されています。

COCO の学習イメージと注釈データを保存するディレクトリを作成します。

imageFolder = fullfile(dataFolder,"images");
captionsFolder = fullfile(dataFolder,"annotations");
if ~exist(imageFolder,'dir')
    mkdir(imageFolder)
    mkdir(captionsFolder)
end

https://cocodataset.org/#download で「2014 Train images」と「2014 Train/Val annotations」のリンクをクリックし、COCO 2014 の学習イメージとキャプションをそれぞれダウンロードします。imageFolder で指定されたフォルダーにイメージ ファイルを解凍します。captionsFolder で指定されたフォルダーに注釈ファイルを解凍します。

annotationFile = fullfile(captionsFolder,"instances_train2014.json");
str = fileread(annotationFile);

学習データの読み取りと前処理

Mask R-CNN に学習させるには、以下のデータが必要です。

  • ネットワークへの入力として機能する RGB イメージ。H x W x 3 の数値配列として指定します。

  • RGB イメージ内のオブジェクトの境界ボックス。NumObjects 行 4 列の行列として指定します。行の形式は [x y w h] です。

  • インスタンス ラベル。NumObjects 行 1 列の string ベクトルとして指定します。

  • インスタンス マスク。各マスクは、イメージ内の 1 つのインスタンスのセグメンテーションです。COCO データ セットは、NumObjects 行 2 列の cell 配列の形式の多角形座標を使用してオブジェクト インスタンスを指定します。配列の各行には、イメージ内の 1 つのインスタンスの境界に沿った多角形の (x,y) 座標が含まれています。ただし、この例の Mask R-CNN には、サイズ H x W x NumObjects の logical 配列として指定されたバイナリ マスクが必要です。

学習データ パラメーターの初期化

trainClassNames = {'person', 'car'};
numClasses = length(trainClassNames);
imageSizeTrain = [800 800 3];

COCO 注釈データの MAT ファイルとしての書式化

MATLAB 用の COCO API を使用すると、注釈データにアクセスできます。https://github.com/cocodataset/cocoapi で [Code] ボタンをクリックして [Download ZIP] を選択し、MATLAB 用の COCO API をダウンロードします。cocoapi-master ディレクトリとその内容を dataFolder で指定されたフォルダーに解凍します。オペレーティング システムで必要な場合は、MatlabAPI サブディレクトリ内の gason.m ファイルの指示に従って、gason パーサーをコンパイルします。

MATLAB 用 COCO API のディレクトリの場所を指定し、そのディレクトリをパスに追加します。

cocoAPIDir = fullfile(dataFolder,"cocoapi-master","MatlabAPI");
addpath(cocoAPIDir);

MAT ファイルを保存するフォルダーを指定します。

unpackAnnotationDir = fullfile(dataFolder,"annotations_unpacked","matFiles");
if ~exist(unpackAnnotationDir,'dir')
    mkdir(unpackAnnotationDir)
end

フォルダー helper にあるサポート ファイルとしてこの例に添付されている補助関数 unpackAnnotations を使用し、COCO の注釈を MAT ファイルに抽出します。各 MAT ファイルは単一の学習イメージに対応し、各学習イメージのファイル名、境界ボックス、インスタンス ラベル、およびインスタンス マスクを含みます。この関数は、関数poly2maskを使用して、多角形座標として指定されたオブジェクト インスタンスをバイナリ マスクに変換します。

helper.unpackAnnotations(trainClassNames,annotationFile,imageFolder,unpackAnnotationDir);
Loading and preparing annotations... DONE (t=9.11s).
Unpacking annotations into MAT files...
Done!

データストアの作成

Mask R-CNN では、RGB 学習イメージ、境界ボックス、インスタンス ラベル、およびインスタンス マスクを含む 1 行 4 列の cell 配列の入力データが必要です。

カスタム読み取り関数 cocoAnnotationMATReader を使用してファイル データストアを作成します。この関数は、アンパックされた注釈 MAT ファイルの内容を読み取り、グレースケール学習イメージを RGB に変換し、データを 1 行 4 列の cell 配列として必要な形式で返します。このカスタム読み取り関数は、フォルダー helper にあるサポート ファイルとしてこの例に添付されています。

ds = fileDatastore(unpackAnnotationDir, ...
    'ReadFcn',@(x)helper.cocoAnnotationMATReader(x,imageFolder));

関数transformを使用して、ネットワークで期待されるサイズになるように学習イメージ、境界ボックス、およびインスタンス マスクを前処理します。関数 transform は、補助関数 preprocessData で指定された演算を使用してデータを処理します。この補助関数は、フォルダー helper にあるサポート ファイルとしてこの例に添付されています。

補助関数 preprocessData は、学習イメージ、境界ボックス、およびインスタンス マスクに対して次の操作を実行します。

  • 関数imresizeを使用して RGB イメージとマスクのサイズを変更し、関数bboxresizeを使用して境界ボックスのサイズを再スケーリングします。補助関数は、イメージ、境界ボックス、またはマスクの小さい方の寸法とターゲット ネットワークの入力サイズが等しくなるように、均一な倍率を選択します。

  • 関数imcropを使用して RGB イメージとマスクをトリミングし、関数bboxcropを使用して境界ボックスをトリミングします。補助関数は、大きい方の寸法とターゲット ネットワークの入力サイズが等しくなるように、イメージ、境界ボックス、またはマスクをトリミングします。

  • COCO データ セット イメージ平均を使用してイメージをゼロ センタリングします (標準偏差の正規化係数は、最初の畳み込み層の重みに含まれています)。

dsTrain = transform(ds,@(x)helper.preprocessData(x,imageSizeTrain));

変換されたデータストアから返されたデータをプレビューします。

data = preview(dsTrain)
data=1×4 cell array
    {800×800×3 single}    {14×4 double}    {14×1 categorical}    {800×800×14 logical}

Mask R-CNN ネットワーク層の作成

Mask R-CNN は、ResNet-50 ベース ネットワークを使用した Faster R-CNN を基に構築されています。事前学習済みの Mask R-CNN ネットワークで学習を転送するには、maskrcnn オブジェクトを使用して事前学習済みのネットワークを読み込み、クラスと入力サイズの新しいセットに合わせてネットワークをカスタマイズします。既定では、maskrcnn オブジェクトは COCO データ セットと同じアンカー ボックスを使用します。

net = maskrcnn("resnet50-coco",trainClassNames,"InputSize",imageSizeTrain)
net = 
  maskrcnn with properties:

      ModelName: 'maskrcnn'
     ClassNames: {'person'  'car'}
      InputSize: [800 800 3]
    AnchorBoxes: [15×2 double]

Mask R-CNN ネットワークの構成パラメーターを含む構造体を作成します。

params = createMaskRCNNConfig(imageSizeTrain,numClasses,[trainClassNames {'background'}]);
params.ClassAgnosticMasks = false;
params.AnchorBoxes = net.AnchorBoxes;
params.FreezeBackbone = true;

学習オプションの指定

SGDM 最適化のオプションを指定します。ネットワークの学習を 10 エポック行います。

initialLearnRate = 0.0012;
momentum = 0.9;
decay = 0.01;
velocity = [];
maxEpochs = 10;
miniBatchSize = 2;

学習データのバッチ処理

カスタム学習ループで観測値のミニバッチを管理するminibatchqueue (Deep Learning Toolbox)オブジェクトを作成します。また、minibatchqueue オブジェクトは、深層学習アプリケーションで自動微分を可能にするdlarray (Deep Learning Toolbox)オブジェクトにデータをキャストします。

miniBatchFcn という名前のカスタム バッチ処理関数を定義します。イメージは、H x W x C x miniBatchSize の形状のバッチになるように 4 番目の次元に沿って連結されます。他のグラウンド トゥルース データは、ミニバッチ サイズに等しい長さの cell 配列で構成されます。

miniBatchFcn = @(img,boxes,labels,masks) deal(cat(4,img{:}),boxes,labels,masks);

イメージ データ用のミニバッチのデータ抽出形式を "SSCB" (spatial、spatial、channel、batch) として指定します。サポートされている GPU を計算に使用できる場合、minibatchqueue オブジェクトは、学習中に並列プールのバックグラウンドでミニバッチを前処理します。

mbqTrain = minibatchqueue(dsTrain,4, ...
    "MiniBatchFormat",["SSCB","","",""], ...
    "MiniBatchSize",miniBatchSize, ...
    "OutputCast",["single","","",""], ...
    "OutputAsDlArray",[true,false,false,false], ...
    "MiniBatchFcn",miniBatchFcn, ...
    "OutputEnvironment",["auto","cpu","cpu","cpu"]);

ネットワークの学習

ネットワークに学習させるには、次のコードで変数 doTrainingtrue に設定します。カスタム学習ループでモデルに学習させます。それぞれの反復で次を行います。

  • 関数next (Deep Learning Toolbox)を使用して、現在のミニバッチ データを読み取ります。

  • 関数dlfeval (Deep Learning Toolbox)と補助関数 networkGradients を使用してモデルの勾配を評価します。サポート関数としてリストされている関数 networkGradients は、学習可能なパラメーターに関する損失勾配、対応するミニバッチの損失、および現在のバッチの状態を返します。

  • 関数sgdmupdate (Deep Learning Toolbox)を使用してネットワーク パラメーターを更新します。

  • 移動平均を使用して、ネットワークの state パラメーターを更新します。

  • 学習の進行状況プロットを更新します。

GPU が利用できる場合、GPU で学習を行います。GPU を使用するには、Parallel Computing Toolbox™、および CUDA® 対応の NVIDIA® GPU が必要です。詳細については、リリース別の GPU サポート (Parallel Computing Toolbox)を参照してください。

doTraining = true;
if doTraining
    
    iteration = 1; 
    start = tic;
    
     % Create subplots for the learning rate and mini-batch loss
    fig = figure;
    [lossPlotter, learningratePlotter] = helper.configureTrainingProgressPlotter(fig);
    
    % Initialize verbose output
    helper.initializeVerboseOutput([]);
    
    % Custom training loop
    for epoch = 1:maxEpochs
        reset(mbqTrain)
        shuffle(mbqTrain)
    
        while hasdata(mbqTrain)
            % Get next batch from minibatchqueue
            [X,gtBox,gtClass,gtMask] = next(mbqTrain);
        
            % Evaluate the model gradients and loss using dlfeval
            [gradients,loss,state,learnables] = dlfeval(@networkGradients,X,gtBox,gtClass,gtMask,net,params);
            %dlnet.State = state;
            
            % Compute the learning rate for the current iteration
            learnRate = initialLearnRate/(1 + decay*(epoch-1));
            
            if(~isempty(gradients) && ~isempty(loss))
                [net.AllLearnables,velocity] = sgdmupdate(learnables,gradients,velocity,learnRate,momentum);
            else
                continue;
            end
            
            % Plot loss/accuracy metric every 10 iterations
            if(mod(iteration,10)==0)
                helper.displayVerboseOutputEveryEpoch(start,learnRate,epoch,iteration,loss);
                D = duration(0,0,toc(start),'Format','hh:mm:ss');
                addpoints(learningratePlotter,iteration,learnRate)
                addpoints(lossPlotter,iteration,double(gather(extractdata(loss))))
                subplot(2,1,2)
                title(strcat("Epoch: ",num2str(epoch),", Elapsed: "+string(D)))
                drawnow
            end
            
            iteration = iteration + 1;    
        end
    
    end
    
    % Save the trained network
    modelDateTime = string(datetime('now','Format',"yyyy-MM-dd-HH-mm-ss"));
    save(strcat("trainedMaskRCNN-",modelDateTime,"-Epoch-",num2str(epoch),".mat"),'net');
    
end
 
Training on GPU.
|=========================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |     Loss     |      Rate       |
|=========================================================================|
|    1    |     10      |    00:00:26    |    1.9042    |     0.0012      | 
|    1    |     20      |    00:00:45    |    2.3645    |     0.0012      | 
|    1    |     30      |    00:01:03    |    2.1728    |     0.0012      | 
|    1    |     40      |    00:01:22    |    2.4587    |     0.0012      | 
|    1    |     50      |    00:01:40    |    1.6101    |     0.0012      | 
|    1    |     60      |    00:01:59    |    1.9428    |     0.0012      | 
|    1    |     70      |    00:02:17    |    2.0966    |     0.0012      | 
|    1    |     80      |    00:02:35    |    1.8483    |     0.0012      | 
|    1    |     90      |    00:02:53    |    1.9071    |     0.0012      | 
|    1    |     100     |    00:03:11    |    2.3982    |     0.0012      | 
|    1    |     110     |    00:03:29    |    1.8156    |     0.0012      | 
|    1    |     120     |    00:03:48    |    1.1133    |     0.0012      | 
|    1    |     130     |    00:04:07    |    1.5866    |     0.0012      | 
|    1    |     140     |    00:04:24    |    1.5608    |     0.0012      | 
|    1    |     150     |    00:04:43    |    0.9455    |     0.0012      | 
|    1    |     160     |    00:05:01    |    1.5179    |     0.0012      | 
|    1    |     170     |    00:05:20    |    1.5809    |     0.0012      | 
|    1    |     180     |    00:05:39    |    1.1198    |     0.0012      | 
|    1    |     190     |    00:05:58    |    1.9142    |     0.0012      | 
|    1    |     200     |    00:06:17    |    1.5293    |     0.0012      | 
|    1    |     210     |    00:06:35    |    1.9376    |     0.0012      | 
|    1    |     220     |    00:06:53    |    1.1024    |     0.0012      | 
|    1    |     230     |    00:07:11    |    2.7115    |     0.0012      | 
|    1    |     240     |    00:07:29    |    1.0415    |     0.0012      | 
|    1    |     250     |    00:07:48    |    2.0512    |     0.0012      | 
|    1    |     260     |    00:08:07    |    1.9210    |     0.0012      | 

学習済みネットワークを使用すると、事前学習済みの Mask R-CNN を使用したインスタンス セグメンテーションの実行の節で説明されているように、テスト イメージでインスタンス セグメンテーションを実行できます。

参考文献

[1] He, Kaiming, Georgia Gkioxari, Piotr Dollár, and Ross Girshick. "Mask R-CNN." Preprint, submitted January 24, 2018. https://arxiv.org/abs/1703.06870.

[2] Lin, Tsung-Yi, Michael Maire, Serge Belongie, Lubomir Bourdev, Ross Girshick, James Hays, Pietro Perona, Deva Ramanan, C. Lawrence Zitnick, and Piotr Dollár. "Microsoft COCO: Common Objects in Context," May 1, 2014. https://arxiv.org/abs/1405.0312v3.

参考

関数

オブジェクト

関連するトピック