Main Content

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

深層学習を使用したセマンティック セグメンテーション

セマンティック セグメンテーション用の学習データの解析

セマンティック セグメンテーション ネットワークに学習させるには、イメージ コレクションと対応するピクセル ラベル付きイメージ コレクションが必要です。ピクセル ラベル付きイメージは、すべてのピクセル値がそのピクセルのカテゴリカル ラベルを表すイメージです。

次のコードでは、イメージの小さなセットとそれに対応するピクセル ラベル付きイメージが読み込まれます。

dataDir = fullfile(toolboxdir('vision'),'visiondata');
imDir = fullfile(dataDir,'building');
pxDir = fullfile(dataDir,'buildingPixelLabels');

imageDatastore を使用してイメージ データを読み込みます。イメージは必要な場合にのみメモリに読み取られるため、イメージ データストアは大規模なイメージ コレクションを効率的に表すことができます。

imds = imageDatastore(imDir);

最初のイメージを読み取って表示します。

I = readimage(imds,1);
figure
imshow(I)

Figure contains an axes object. The axes object contains an object of type image.

pixelLabelDatastore を使用してピクセル ラベル イメージを読み込み、ラベル ID とカテゴリカル名の間のマッピングを定義します。ここで使用されているデータセットでは、ラベルは "sky"、"grass"、"building"、および "sidewalk" です。これらのクラスのラベル ID はそれぞれ 1、2、3、4 です。

クラス名を定義します。

classNames = ["sky" "grass" "building" "sidewalk"];

各クラス名のラベル ID を定義します。

pixelLabelID = [1 2 3 4];

pixelLabelDatastore を作成します。

pxds = pixelLabelDatastore(pxDir,classNames,pixelLabelID);

最初のピクセル ラベル イメージを読み取ります。

C = readimage(pxds,1);

出力 C は categorical 行列です。ここで、C(i,j) はピクセル I(i,j) のカテゴリカル ラベルです。

C(5,5)
ans = categorical
     sky 

イメージにピクセル ラベルを重ね合わせて、イメージのさまざまな部分へのラベル付けを確認します。

B = labeloverlay(I,C);
figure
imshow(B)

Figure contains an axes object. The axes object contains an object of type image.

カテゴリカル出力形式を使うと、クラス名別での操作が必要なタスクが簡略化されます。たとえば、次のように建物だけのバイナリ マスクを作成できます。

buildingMask = C == 'building';

figure
imshowpair(I, buildingMask,'montage')

Figure contains an axes object. The axes object contains an object of type image.

セマンティック セグメンテーション ネットワークの作成

簡単なセマンティック セグメンテーション ネットワークを作成し、多くのセマンティック セグメンテーション ネットワークで検出された共通の層について学習します。セマンティック セグメンテーション ネットワークの共通パターンでは、畳み込み層と ReLU 層間でイメージをダウンサンプリングした後、入力サイズを一致させるために出力をアップサンプリングする必要があります。この操作は、イメージ ピラミッドを使用した標準のスケールスペース解析に類似しています。ただし、このプロセス中、ネットワークはセグメント化するクラスの特定のセットに対して最適化されている非線形フィルターを使用して操作を実行します。

イメージ入力層の作成

セマンティック セグメンテーション ネットワークは imageInputLayer から始まります。これは、ネットワークで処理できる最小のイメージ サイズを定義します。ほとんどのセマンティック セグメンテーション ネットワークは完全畳み込みです。つまり、指定の入力サイズよりも大きいイメージを処理できます。ここでは、64x64 の RGB イメージを処理するネットワークで [32 32 3] のイメージ サイズが使用されています。

inputSize = [32 32 3];
imgLayer = imageInputLayer(inputSize)
imgLayer = 
  ImageInputLayer with properties:

                Name: ''
           InputSize: [32 32 3]

   Hyperparameters
    DataAugmentation: 'none'
       Normalization: 'zerocenter'

ダウンサンプリング ネットワークの作成

畳み込み層と ReLU 層から始めます。畳み込み層の出力サイズが入力サイズと同じになるように、畳み込み層のパディングが選択されています。これによって、ネットワークで処理を進める間、ほとんどの層間の入力サイズと出力サイズが変わらないため、ネットワークが作成しやすくなります。

filterSize = 3;
numFilters = 32;
conv = convolution2dLayer(filterSize,numFilters,'Padding',1);
relu = reluLayer();

ダウンサンプリングは、最大プーリング層を使用して実行されます。'Stride' パラメーターを 2 に設定することで、入力を 2 の係数でダウンサンプリングする最大プーリング層を作成します。

poolSize = 2;
maxPoolDownsample2x = maxPooling2dLayer(poolSize,'Stride',2);

畳み込み層、ReLU 層および最大プール層を積み重ねて、その入力を 4 の係数でダウンサンプリングするネットワークを作成します。

downsamplingLayers = [
    conv
    relu
    maxPoolDownsample2x
    conv
    relu
    maxPoolDownsample2x
    ]
downsamplingLayers = 
  6x1 Layer array with layers:

     1   ''   Convolution   32 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     2   ''   ReLU          ReLU
     3   ''   Max Pooling   2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     4   ''   Convolution   32 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     5   ''   ReLU          ReLU
     6   ''   Max Pooling   2x2 max pooling with stride [2  2] and padding [0  0  0  0]

アップサンプリング ネットワークの作成

アップサンプリングは、転置畳み込み層 (一般的には "deconv" または "逆畳み込み" 層とも呼びます) を使用して実行されます。転置畳み込みがアップサンプリングに使用されている場合、アップサンプリングとフィルター処理が同時に実行されます。

2 でアップサンプリングする転置畳み込み層を作成します。

filterSize = 4;
transposedConvUpsample2x = transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);

出力サイズが入力サイズの 2 倍になるよう 'Cropping' パラメーターが 1 に設定されています。

転置畳み込み層と ReLU 層を積み重ねます。この層のセットへの入力は 4 でアップサンプリングされます。

upsamplingLayers = [
    transposedConvUpsample2x
    relu
    transposedConvUpsample2x
    relu
    ]
upsamplingLayers = 
  4x1 Layer array with layers:

     1   ''   Transposed Convolution   32 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
     2   ''   ReLU                     ReLU
     3   ''   Transposed Convolution   32 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
     4   ''   ReLU                     ReLU

ピクセル分類層の作成

最終的な層のセットは、ピクセル分類の作成を行います。これらの最終層は、入力イメージと同じ空間次元 (高さと幅) を持つ入力を処理します。ただし、チャネル数 (3 番目の次元) は大きく、最後の転置畳み込み層フィルター数と同じになります。この 3 つ目の次元を、セグメント化するクラス数まで絞り込む必要があります。これを実行するには、フィルターの数がクラス数 (3 など) と一致する 1 行 1 列の畳み込み層を使用します。

入力特徴マップの 3 番目の次元をクラス数まで結合する畳み込み層を作成します。

numClasses = 3;
conv1x1 = convolution2dLayer(1,numClasses);

この 1 行 1 列の畳み込み層の後に、ソフトマックス層とピクセル分類層が続きます。これらの 2 つの層が結合されて、各イメージ ピクセルのカテゴリカル ラベルが予測されます。

finalLayers = [
    conv1x1
    softmaxLayer()
    pixelClassificationLayer()
    ]
finalLayers = 
  3x1 Layer array with layers:

     1   ''   Convolution                  3 1x1 convolutions with stride [1  1] and padding [0  0  0  0]
     2   ''   Softmax                      softmax
     3   ''   Pixel Classification Layer   Cross-entropy loss 

すべての層の積み重ね

すべての層を積み重ねて、セマンティック セグメンテーション ネットワークを完成させます。

net = [
    imgLayer    
    downsamplingLayers
    upsamplingLayers
    finalLayers
    ]
net = 
  14x1 Layer array with layers:

     1   ''   Image Input                  32x32x3 images with 'zerocenter' normalization
     2   ''   Convolution                  32 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     3   ''   ReLU                         ReLU
     4   ''   Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     5   ''   Convolution                  32 3x3 convolutions with stride [1  1] and padding [1  1  1  1]
     6   ''   ReLU                         ReLU
     7   ''   Max Pooling                  2x2 max pooling with stride [2  2] and padding [0  0  0  0]
     8   ''   Transposed Convolution       32 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
     9   ''   ReLU                         ReLU
    10   ''   Transposed Convolution       32 4x4 transposed convolutions with stride [2  2] and output cropping [1  1]
    11   ''   ReLU                         ReLU
    12   ''   Convolution                  3 1x1 convolutions with stride [1  1] and padding [0  0  0  0]
    13   ''   Softmax                      softmax
    14   ''   Pixel Classification Layer   Cross-entropy loss 

このネットワークには、Deep Learning Toolbox™ の trainNetwork を使用して学習させることができます。

セマンティック セグメンテーション ネットワークの学習

学習データを読み込みます。

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');
imageDir = fullfile(dataSetDir,'trainingImages');
labelDir = fullfile(dataSetDir,'trainingLabels');

イメージのイメージ データストアを作成します。

imds = imageDatastore(imageDir);

グラウンド トゥルース ピクセル ラベル用の pixelLabelDatastore を作成します。

classNames = ["triangle","background"];
labelIDs   = [255 0];
pxds = pixelLabelDatastore(labelDir,classNames,labelIDs);

学習イメージとグラウンド トゥルース ピクセル ラベルを可視化します。

I = read(imds);
C = read(pxds);

I = imresize(I,5);
L = imresize(uint8(C{1}),5);
imshowpair(I,L,'montage')

セマンティック セグメンテーション ネットワークを作成します。このネットワークでは、ダウンサンプリングおよびアップサンプリングの設計に基づいてシンプルなセマンティック セグメンテーション ネットワークを使用します。

numFilters = 64;
filterSize = 3;
numClasses = 2;
layers = [
    imageInputLayer([32 32 1])
    convolution2dLayer(filterSize,numFilters,'Padding',1)
    reluLayer()
    maxPooling2dLayer(2,'Stride',2)
    convolution2dLayer(filterSize,numFilters,'Padding',1)
    reluLayer()
    transposedConv2dLayer(4,numFilters,'Stride',2,'Cropping',1);
    convolution2dLayer(1,numClasses);
    softmaxLayer()
    pixelClassificationLayer()
    ];

学習オプションを設定します。

opts = trainingOptions('sgdm', ...
    'InitialLearnRate',1e-3, ...
    'MaxEpochs',100, ...
    'MiniBatchSize',64);

イメージ データストアとピクセル ラベル データストアを学習用に統合します。

trainingData = combine(imds,pxds);

ネットワークに学習をさせます。

net = trainNetwork(trainingData,layers,opts);
Training on single CPU.
Initializing input data normalization.
|========================================================================================|
|  Epoch  |  Iteration  |  Time Elapsed  |  Mini-batch  |  Mini-batch  |  Base Learning  |
|         |             |   (hh:mm:ss)   |   Accuracy   |     Loss     |      Rate       |
|========================================================================================|
|       1 |           1 |       00:00:00 |       58.11% |       1.3458 |          0.0010 |
|      17 |          50 |       00:00:12 |       97.30% |       0.0924 |          0.0010 |
|      34 |         100 |       00:00:24 |       98.09% |       0.0575 |          0.0010 |
|      50 |         150 |       00:00:37 |       98.56% |       0.0424 |          0.0010 |
|      67 |         200 |       00:00:49 |       98.48% |       0.0435 |          0.0010 |
|      84 |         250 |       00:01:02 |       98.66% |       0.0363 |          0.0010 |
|     100 |         300 |       00:01:14 |       98.90% |       0.0310 |          0.0010 |
|========================================================================================|
Training finished: Reached final iteration.

テスト イメージを読み取って表示します。

testImage = imread('triangleTest.jpg');
imshow(testImage)

テスト イメージをセグメント化し、結果を表示します。

C = semanticseg(testImage,net);
B = labeloverlay(testImage,C);
imshow(B)

セマンティック セグメンテーションの結果の評価と検査

テスト データ セットをインポートして、事前学習済みのセマンティック セグメンテーション ネットワークを実行し、予測される結果に対してセマンティック セグメンテーションの品質メトリクスを検査します。

データセットのインポート

triangleImages データセットには、グラウンド トゥルース ラベルの付いた 100 個のテスト イメージがあります。データセットの場所を定義します。

dataSetDir = fullfile(toolboxdir('vision'),'visiondata','triangleImages');

テスト イメージの場所を定義します。

testImagesDir = fullfile(dataSetDir,'testImages');

テスト イメージを保持する imageDatastore オブジェクトを作成します。

imds = imageDatastore(testImagesDir);

グラウンド トゥルース ラベルの場所を定義します。

testLabelsDir = fullfile(dataSetDir,'testLabels');

クラス名と関連するラベル ID を定義します。ラベル ID は、イメージ ファイルで各クラスを表すために使用されるピクセル値です。

classNames = ["triangle" "background"];
labelIDs = [255 0];

テスト イメージのグラウンド トゥルース ピクセル ラベルを保持する pixelLabelDatastore オブジェクトを作成します。

pxdsTruth = pixelLabelDatastore(testLabelsDir,classNames,labelIDs);

セマンティック セグメンテーション分類器の実行

triangleImages の学習イメージで学習させられたセマンティック セグメンテーション ネットワークを読み込みます。

net = load('triangleSegmentationNetwork.mat');
net = net.net;

テスト イメージでネットワークを実行します。予測されたラベルは、一時ディレクトリのディスクに書き込まれ、pixelLabelDatastore オブジェクトとして返されます。

pxdsResults = semanticseg(imds,net,"WriteLocation",tempdir);
Running semantic segmentation network
-------------------------------------
* Processed 100 images.

予測の品質の評価

予測されたラベルはグラウンド トゥルース ラベルと比較されます。セマンティック セグメンテーション メトリクスが計算されている間、進行状況がコマンド ウィンドウに出力されます。

metrics = evaluateSemanticSegmentation(pxdsResults,pxdsTruth);
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: global accuracy, class accuracy, IoU, weighted IoU, BF score.
* Processed 100 images.
* Finalizing... Done.
* Data set metrics:

    GlobalAccuracy    MeanAccuracy    MeanIoU    WeightedIoU    MeanBFScore
    ______________    ____________    _______    ___________    ___________

       0.90624          0.95085       0.61588      0.87529        0.40652  

クラス メトリクスの検査

データセットの各クラスの分類の精度、Intersection over Union (IoU)、および境界 F-1 スコアを表示します。

metrics.ClassMetrics
ans=2×3 table
                  Accuracy      IoU      MeanBFScore
                  ________    _______    ___________

    triangle            1     0.33005     0.028664  
    background     0.9017      0.9017      0.78438  

混同行列の表示

混同行列を表示します。

metrics.ConfusionMatrix
ans=2×2 table
                  triangle    background
                  ________    __________

    triangle        4730            0   
    background      9601        88069   

正規化された混同行列を Figure ウィンドウのヒート マップとして可視化します。

normConfMatData = metrics.NormalizedConfusionMatrix.Variables;
figure
h = heatmap(classNames,classNames,100*normConfMatData);
h.XLabel = 'Predicted Class';
h.YLabel = 'True Class';
h.Title = 'Normalized Confusion Matrix (%)';

Figure contains an object of type heatmap. The chart of type heatmap has title Normalized Confusion Matrix (%).

イメージ メトリクスの検査

イメージごとの Intersection over Union (IoU) のヒストグラムを可視化します。

imageIoU = metrics.ImageMetrics.MeanIoU;
figure
histogram(imageIoU)
title('Image Mean IoU')

Figure contains an axes object. The axes object with title Image Mean IoU contains an object of type histogram.

最小の IoU を持つテスト イメージを見つけます。

[minIoU, worstImageIndex] = min(imageIoU);
minIoU = minIoU(1);
worstImageIndex = worstImageIndex(1);

比較用に、最悪の IoU を持つテスト イメージ、そのグラウンド トゥルース ラベル、およびその予測されたラベルを読み取ります。

worstTestImage = readimage(imds,worstImageIndex);
worstTrueLabels = readimage(pxdsTruth,worstImageIndex);
worstPredictedLabels = readimage(pxdsResults,worstImageIndex);

ラベル イメージを Figure ウィンドウに表示できるイメージに変換します。

worstTrueLabelImage = im2uint8(worstTrueLabels == classNames(1));
worstPredictedLabelImage = im2uint8(worstPredictedLabels == classNames(1));

最悪のテスト イメージ、グラウンド トゥルースおよび予測を表示します。

worstMontage = cat(4,worstTestImage,worstTrueLabelImage,worstPredictedLabelImage);
worstMontage = imresize(worstMontage,4,"nearest");
figure
montage(worstMontage,'Size',[1 3])
title(['Test Image vs. Truth vs. Prediction. IoU = ' num2str(minIoU)])

Figure contains an axes object. The axes object with title Test Image vs. Truth vs. Prediction. IoU = 0.55519 contains an object of type image.

同様に、最高の IoU を持つテスト イメージを見つけます。

[maxIoU, bestImageIndex] = max(imageIoU);
maxIoU = maxIoU(1);
bestImageIndex = bestImageIndex(1);

前の手順を繰り返して、最高の IoU を持つテスト イメージをそのグラウンド トゥルースおよび予測されたラベルと共に読み取り、変換し、表示します。

bestTestImage = readimage(imds,bestImageIndex);
bestTrueLabels = readimage(pxdsTruth,bestImageIndex);
bestPredictedLabels = readimage(pxdsResults,bestImageIndex);

bestTrueLabelImage = im2uint8(bestTrueLabels == classNames(1));
bestPredictedLabelImage = im2uint8(bestPredictedLabels == classNames(1));

bestMontage = cat(4,bestTestImage,bestTrueLabelImage,bestPredictedLabelImage);
bestMontage = imresize(bestMontage,4,"nearest");
figure
montage(bestMontage,'Size',[1 3])
title(['Test Image vs. Truth vs. Prediction. IoU = ' num2str(maxIoU)])

Figure contains an axes object. The axes object with title Test Image vs. Truth vs. Prediction. IoU = 0.72502 contains an object of type image.

評価するメトリクスの指定

オプションで、'Metrics' パラメーターを使用して評価するメトリクスをリストします。

計算するメトリクスを定義します。

evaluationMetrics = ["accuracy" "iou"];

triangleImages テスト データセットについてこれらのメトリクスを計算します。

metrics = evaluateSemanticSegmentation(pxdsResults,pxdsTruth,"Metrics",evaluationMetrics);
Evaluating semantic segmentation results
----------------------------------------
* Selected metrics: class accuracy, IoU.
* Processed 100 images.
* Finalizing... Done.
* Data set metrics:

    MeanAccuracy    MeanIoU
    ____________    _______

      0.95085       0.61588

クラスごとに選択したメトリクスを表示します。

metrics.ClassMetrics
ans=2×2 table
                  Accuracy      IoU  
                  ________    _______

    triangle            1     0.33005
    background     0.9017      0.9017

セマンティック セグメンテーションのピクセル ラベル付きデータセットのインポート

この例では、セマンティック セグメンテーション ネットワークのピクセル ラベル付きデータセットをインポートする方法を示します。

ピクセル ラベル付きデータセットは、セマンティック セグメンテーション ネットワークに学習させるために使用されるイメージ コレクションと対応するグラウンド トゥルース ピクセル ラベルのセットです。ピクセルごとのラベルで注釈が付けられたイメージを提供する多くのパブリック データセットがあります。これらのタイプのデータセットをインポートする手順を示すために、この例では、ケンブリッジ大学の CamVid データセット [1] を使用します。

CamVid データセットは、運転中に得られた路上レベルでのビューが含まれるイメージ コレクションです。データセットは、車、歩行者、道路を含む 32 個のセマンティック クラスについてピクセルレベルのラベルを提供します。CamVid をインポートするための手順を使用して、他のピクセル ラベル付きデータセットをインポートできます。

CamVid データセットのダウンロード

次の URL から CamVid イメージ データをダウンロードします。

imageURL = 'http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/files/701_StillsRaw_full.zip';
labelURL = 'http://web4.cs.ucl.ac.uk/staff/g.brostow/MotionSegRecData/data/LabeledApproved_full.zip';

outputFolder = fullfile(tempdir, 'CamVid');
imageDir = fullfile(outputFolder,'images');
labelDir = fullfile(outputFolder,'labels');

if ~exist(outputFolder, 'dir')
    disp('Downloading 557 MB CamVid data set...');
    
    unzip(imageURL, imageDir);
    unzip(labelURL, labelDir);
end

メモ: データのダウンロードにかかる時間はインターネット接続の速度によって異なります。上記で使用したコマンドは、ダウンロードが完了するまで MATLAB® をブロックします。別の方法として、Web ブラウザーを使用して、データセットをローカル ディスクにまずダウンロードしておくことができます。Web からダウンロードしたファイルを使用するには、上記の変数 outputFolder の値を、ダウンロードしたファイルの場所に変更します。

CamVid ピクセル ラベル

CamVid データセットはピクセル ラベルを RGB イメージとして符号化します。RGB イメージでは各クラスが RGB カラーで表されます。以下に、データセットで RGB 符号化と共に定義するクラスを示します。

classNames = [ ...
    "Animal", ...
    "Archway", ...
    "Bicyclist", ...
    "Bridge", ...
    "Building", ...
    "Car", ...
    "CartLuggagePram", ...
    "Child", ...
    "Column_Pole", ...
    "Fence", ...
    "LaneMkgsDriv", ...
    "LaneMkgsNonDriv", ...
    "Misc_Text", ...
    "MotorcycleScooter", ...
    "OtherMoving", ...
    "ParkingBlock", ...
    "Pedestrian", ...
    "Road", ...
    "RoadShoulder", ...
    "Sidewalk", ...
    "SignSymbol", ...
    "Sky", ...
    "SUVPickupTruck", ...
    "TrafficCone", ...
    "TrafficLight", ...
    "Train", ...
    "Tree", ...
    "Truck_Bus", ...
    "Tunnel", ...
    "VegetationMisc", ...
    "Wall"];

classNames(k)labelIDs(k,:) に対応するようにラベル インデックスとクラス名間のマッピングを定義します。

labelIDs = [ ...
    064 128 064; ... % "Animal"
    192 000 128; ... % "Archway"
    000 128 192; ... % "Bicyclist"
    000 128 064; ... % "Bridge"
    128 000 000; ... % "Building"
    064 000 128; ... % "Car"
    064 000 192; ... % "CartLuggagePram"
    192 128 064; ... % "Child"
    192 192 128; ... % "Column_Pole"
    064 064 128; ... % "Fence"
    128 000 192; ... % "LaneMkgsDriv"
    192 000 064; ... % "LaneMkgsNonDriv"
    128 128 064; ... % "Misc_Text"
    192 000 192; ... % "MotorcycleScooter"
    128 064 064; ... % "OtherMoving"
    064 192 128; ... % "ParkingBlock"
    064 064 000; ... % "Pedestrian"
    128 064 128; ... % "Road"
    128 128 192; ... % "RoadShoulder"
    000 000 192; ... % "Sidewalk"
    192 128 128; ... % "SignSymbol"
    128 128 128; ... % "Sky"
    064 128 192; ... % "SUVPickupTruck"
    000 000 064; ... % "TrafficCone"
    000 064 064; ... % "TrafficLight"
    192 064 128; ... % "Train"
    128 128 000; ... % "Tree"
    192 128 192; ... % "Truck_Bus"
    064 000 064; ... % "Tunnel"
    192 192 000; ... % "VegetationMisc"
    064 192 000];    % "Wall"

他のデータセットは符号化データの形式が異なることに注意してください。たとえば、PASCAL VOC [2] データセットでは、0 ~ 21 の数値ラベル ID を使用してそれらのクラス ラベルを符号化します。

CamVid イメージのいずれか 1 つに対してピクセル ラベルを可視化します。

labels = imread(fullfile(labelDir,'0001TP_006690_L.png'));
figure
imshow(labels)

% Add colorbar to show class to color mapping.
N = numel(classNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(labelIDs./255)

CamVid データの読み込み

ピクセル ラベル付きデータセットは、imageDatastore および pixelLabelDatastore を使用して読み込むことができます。

CamVid イメージを読み込む imageDatastore を作成します。

imds = imageDatastore(fullfile(imageDir,'701_StillsRaw_full'));

CamVid ピクセル ラベルを読み込む pixelLabelDatastore を作成します。

pxds = pixelLabelDatastore(labelDir,classNames,labelIDs);

10 番目のイメージと対応するピクセル ラベル イメージを読み取ります。

I = readimage(imds,10);
C = readimage(pxds,10);

ピクセル ラベル イメージは categorical 配列として返されます。この配列では、C(i,j) がピクセル I(i,j) に割り当てられたカテゴリカル ラベルになります。イメージの上にピクセル ラベル イメージを表示します。

B = labeloverlay(I,C,'Colormap',labelIDs./255);
figure
imshow(B)

% Add a colorbar.
N = numel(classNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(labelIDs./255)

undefined ラベルまたは void ラベル

ピクセル ラベル付きデータセットには "undefined" ラベルまたは "void" ラベルを含めるのが一般的です。これらは、ラベル付けされていないピクセルを示すために使用されます。たとえば、CamVid では、ラベル ID [0 0 0] は "void" クラスを指定するために使用されます。学習アルゴリズムと評価アルゴリズムでは、どの計算にもこれらのラベルが含まれないものと見なされます。

"void" クラスは、pixelLabelDatastore を使用するときに明示的に名前を付ける必要はありません。クラス名にマッピングされていないラベル ID には自動的に "undefined" のラベルが付き、計算対象から除外されます。未定義のピクセルを確認するには、isundefined を使用してマスクを作成した後、そのマスクをイメージの上に表示します。

undefinedPixels = isundefined(C);
B = labeloverlay(I,undefinedPixels);
figure
imshow(B)
title('Undefined Pixel Labels')

クラスの結合

パブリック データセットを使用する場合は、アプリケーションにより適合するよういくつかのクラスを結合しなければならない場合があります。たとえば、シーンを道路、空、自動車、歩行者の 4 つのクラスと背景にセグメント化するセマンティック セグメンテーション ネットワークに学習させる場合を考えます。これを CamVid データセットで行うには、上記で定義したラベル ID を新しいクラスに合わせてグループ化します。最初に、新しいクラス名を定義します。

newClassNames = ["road","sky","vehicle","pedestrian","background"];

次に、M 行 3 列の行列のセル配列を使用してラベル ID をグループ化します。

groupedLabelIDs = {
    % road
    [
    128 064 128; ... % "Road"
    128 000 192; ... % "LaneMkgsDriv"
    192 000 064; ... % "LaneMkgsNonDriv"
    000 000 192; ... % "Sidewalk" 
    064 192 128; ... % "ParkingBlock"
    128 128 192; ... % "RoadShoulder"
    ]
   
    % "sky"
    [
    128 128 128; ... % "Sky"
    ]
    
    % "vehicle"
    [
    064 000 128; ... % "Car"
    064 128 192; ... % "SUVPickupTruck"
    192 128 192; ... % "Truck_Bus"
    192 064 128; ... % "Train"
    000 128 192; ... % "Bicyclist"
    192 000 192; ... % "MotorcycleScooter"
    128 064 064; ... % "OtherMoving"
    ]
     
    % "pedestrian"
    [
    064 064 000; ... % "Pedestrian"
    192 128 064; ... % "Child"
    064 000 192; ... % "CartLuggagePram"
    064 128 064; ... % "Animal"
    ]
    
    % "background"      
    [
    128 128 000; ... % "Tree"
    192 192 000; ... % "VegetationMisc"    
    192 128 128; ... % "SignSymbol"
    128 128 064; ... % "Misc_Text"
    000 064 064; ... % "TrafficLight"  
    064 064 128; ... % "Fence"
    192 192 128; ... % "Column_Pole"
    000 000 064; ... % "TrafficCone"
    000 128 064; ... % "Bridge"
    128 000 000; ... % "Building"
    064 192 000; ... % "Wall"
    064 000 064; ... % "Tunnel"
    192 000 128; ... % "Archway"
    ]
    };

新しいクラスとラベル ID を使用して pixelLabelDatastore を作成します。

pxds = pixelLabelDatastore(labelDir,newClassNames,groupedLabelIDs);

10 番目のピクセル ラベル イメージを読み取り、イメージの上に表示します。

C = readimage(pxds,10);
cmap = jet(numel(newClassNames));
B = labeloverlay(I,C,'Colormap',cmap);
figure
imshow(B)

% add colorbar
N = numel(newClassNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(newClassNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(cmap)

新しいクラス名を持つ pixelLabelDatastore を使用すると、元の CamVid ピクセル ラベルを変更せずに、4 クラスについてネットワークに学習させることができます。

参考文献

[1] Brostow, Gabriel J., Julien Fauqueur, and Roberto Cipolla."Semantic object classes in video: A high-definition ground truth database." Pattern Recognition Letters 30.2 (2009): 88-97.

[2] Everingham, M., et al. "The PASCAL visual object classes challenge 2012 results." http://www. pascal-network. org/challenges/VOC/voc2012/workshop/index. html Vol. 5. 2012.