Main Content

このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。

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

この例では、セマンティック セグメンテーション ネットワークを使用してイメージをセグメント化する方法を説明します。

セマンティック セグメンテーション ネットワークはイメージ内のすべてのピクセルを分類して、クラスごとにセグメント化されたイメージを作成します。セマンティック セグメンテーションの応用例としては、自動運転のための道路セグメンテーションや医療診断のための癌細胞セグメンテーションなどがあります。詳細については、深層学習を使用したセマンティック セグメンテーション入門 (Computer Vision Toolbox)を参照してください。

この例では、まず、事前学習済みの Deeplab v3+ [1] ネットワークを使用してイメージをセグメント化する方法を説明します。これは、畳み込みニューラル ネットワーク (CNN) の一種で、セマンティック イメージ セグメンテーション用に設計されています。セマンティック セグメンテーション ネットワークのもう 1 つのタイプは U-Net です。または、データセットをダウンロードし、転移学習を使用して Deeplab v3 ネットワークに学習させることもできます。ここで示す学習手順は、他のタイプのセマンティック セグメンテーション ネットワークにも適用することができます。

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

この例を実行するには、CUDA 対応 NVIDIA™ GPU の使用が強く推奨されます。GPU を使用するには Parallel Computing Toolbox™ が必要です。サポートされる Compute Capability の詳細については、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。

事前学習済みのセマンティック セグメンテーション ネットワークのダウンロード

CamVid データセットで学習させた事前学習済みのバージョンの DeepLab v3+ をダウンロードします。

pretrainedURL = "https://ssd.mathworks.com/supportfiles/vision/data/deeplabv3plusResnet18CamVid_v2.zip";
pretrainedFolder = fullfile(tempdir,"pretrainedNetwork");
pretrainedNetworkZip = fullfile(pretrainedFolder,"deeplabv3plusResnet18CamVid_v2.zip"); 
if ~exist(pretrainedNetworkZip,'file')
    mkdir(pretrainedFolder);
    disp("Downloading pretrained network (58 MB)...");
    websave(pretrainedNetworkZip,pretrainedURL);
end
Downloading pretrained network (58 MB)...
unzip(pretrainedNetworkZip, pretrainedFolder)

事前学習済みのネットワークを読み込みます。

pretrainedNetwork = fullfile(pretrainedFolder,"deeplabv3plusResnet18CamVid_v2.mat");  
data = load(pretrainedNetwork);
net = data.net;

分類用にこのネットワークに学習させたクラスを設定します。

classes = getClassNames()
classes = 11×1 string
    "Sky"
    "Building"
    "Pole"
    "Road"
    "Pavement"
    "Tree"
    "SignSymbol"
    "Fence"
    "Car"
    "Pedestrian"
    "Bicyclist"

セマンティック イメージ セグメンテーションの実行

分類用にこのネットワークに学習させたクラスを含むイメージを読み取ります。

I = imread("parkinglot_left.png");

イメージのサイズをネットワークの入力サイズに変更します。

inputSize = net.Layers(1).InputSize;
I = imresize(I,inputSize(1:2));

関数 semanticseg と事前学習済みのネットワークを使用して、セマンティック セグメンテーションを実行します。

C = semanticseg(I,net);

labeloverlay を使用して、セグメント化の結果をイメージに重ね合わせます。オーバーレイのカラーマップを、CamVid データセット [2] で定義されたカラーマップの値に設定します。

cmap = camvidColorMap;
B = labeloverlay(I,C,Colormap=cmap,Transparency=0.4);
figure
imshow(B)
pixelLabelColorbar(cmap, classes);

このネットワークは、市街地の走行イメージで事前学習されていますが、駐車場のシーンでも妥当な結果を生成します。セグメント化の結果を改善するには、駐車場のシーンを含む追加のイメージでネットワークに再学習させる必要があります。この例の残りの部分では、転移学習を使用してセマンティック セグメンテーション ネットワークの学習を行う方法を説明します。

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

この例では、事前学習済みの ResNet-18 ネットワークから、重みが初期化された Deeplab v3+ ネットワークに学習させます。ResNet-18 は、処理するリソースが限られている用途に非常に適した効率的なネットワークです。用途の要件によって、MobileNet v2 や ResNet-50 など、その他の事前学習済みのネットワークも使用できます。詳細については、事前学習済みの深層ニューラル ネットワークを参照してください。

事前学習済みの ResNet-18 ネットワークを取得するには、関数 imagePretrainedNetwork を使用します。ResNet-18 には、Deep Learning Toolbox™ Model for ResNet-18 Network サポート パッケージが必要です。このサポート パッケージがインストールされていない場合、関数によってダウンロード用リンクが表示されます。

imagePretrainedNetwork("resnet18")
ans = 
  dlnetwork with properties:

         Layers: [70×1 nnet.cnn.layer.Layer]
    Connections: [77×2 table]
     Learnables: [82×3 table]
          State: [40×3 table]
     InputNames: {'data'}
    OutputNames: {'prob'}
    Initialized: 1

  View summary with summary.

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"); 
labelsZip = fullfile(outputFolder,"labels.zip");
imagesZip = fullfile(outputFolder,"images.zip");

if ~exist(labelsZip, 'file') || ~exist(imagesZip,'file')   
    mkdir(outputFolder)
       
    disp("Downloading 16 MB CamVid dataset labels..."); 
    websave(labelsZip, labelURL);
    unzip(labelsZip, fullfile(outputFolder,"labels"));
    
    disp("Downloading 557 MB CamVid dataset images...");  
    websave(imagesZip, imageURL);       
    unzip(imagesZip, fullfile(outputFolder,"images"));    
end
Downloading 16 MB CamVid dataset labels...
Downloading 557 MB CamVid dataset images...

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

CamVid イメージの読み込み

imageDatastore を使用して CamVid イメージを読み込みます。imageDatastore は、ディスク上の大規模なイメージ コレクションを効率的に読み込むことができます。

imgDir = fullfile(outputFolder,"images","701_StillsRaw_full");
imds = imageDatastore(imgDir);

イメージのうちの 1 つを表示します。

I = readimage(imds,559);
I = histeq(I);
imshow(I)

CamVid のピクセル ラベル付きイメージの読み込み

pixelLabelDatastore (Computer Vision Toolbox) を使用して、CamVid のピクセル ラベル イメージ データを読み込みます。pixelLabelDatastore は、ピクセル ラベル データとラベル ID をクラス名のマッピングにカプセル化します。

学習を容易にするために、CamVid の元の 32 個のクラスを 11 個のクラスにグループ化します。32 個のクラスを 11 個に減らすには、元のデータセットの複数のクラスをグループとしてまとめます。たとえば、"Car"、"SUVPickupTruck"、"Truck_Bus"、"Train"、および "OtherMoving" を組み合わせたものを "Car" とします。この例の最後にリストされているサポート関数 camvidPixelLabelIDs を使用することで、グループ化されたラベル ID が返されます。

labelIDs = camvidPixelLabelIDs();

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

labelDir = fullfile(outputFolder,"labels");
pxds = pixelLabelDatastore(labelDir,classes,labelIDs);

イメージの上に重ね合わせることで、ピクセル ラベル付きイメージのうちの 1 つを読み取って表示します。色の重ね合わせが存在しない領域にはピクセル ラベルはなく、学習中は使用されません。

C = readimage(pxds,559);
cmap = camvidColorMap;
B = labeloverlay(I,C,ColorMap=cmap);
imshow(B)
pixelLabelColorbar(cmap,classes);

データセット統計の解析

CamVid データセット内のクラス ラベルの分布を表示するには、countEachLabel (Computer Vision Toolbox) を使用します。この関数は、クラス ラベル別にピクセルの数をカウントします。

tbl = countEachLabel(pxds)
tbl=11×3 table
         Name         PixelCount    ImagePixelCount
    ______________    __________    _______________

    {'Sky'       }    7.6801e+07      4.8315e+08   
    {'Building'  }    1.1737e+08      4.8315e+08   
    {'Pole'      }    4.7987e+06      4.8315e+08   
    {'Road'      }    1.4054e+08      4.8453e+08   
    {'Pavement'  }    3.3614e+07      4.7209e+08   
    {'Tree'      }    5.4259e+07       4.479e+08   
    {'SignSymbol'}    5.2242e+06      4.6863e+08   
    {'Fence'     }    6.9211e+06       2.516e+08   
    {'Car'       }    2.4437e+07      4.8315e+08   
    {'Pedestrian'}    3.4029e+06      4.4444e+08   
    {'Bicyclist' }    2.5912e+06      2.6196e+08   

ピクセル数をクラス別に可視化します。

frequency = tbl.PixelCount/sum(tbl.PixelCount);

bar(1:numel(classes),frequency)
xticks(1:numel(classes)) 
xticklabels(tbl.Name)
xtickangle(45)
ylabel("Frequency")

観測値の数がすべてのクラスで等しいことが理想的です。しかし、CamVid 内のクラスは不均衡です。これは、路上シーンの自動車データセットに共通する問題です。こうしたシーンには、歩行者や自転車運転者のピクセルよりも多くの空、建物、および道路のピクセルが含まれます。これは、空、建物、および道路がイメージ内でより広い領域を占めているためです。学習では上位クラスを優先してバイアスがかけられるため、正しく処理されていない場合は、こうした不均衡が学習プロセスに悪影響を及ぼす可能性があります。この例の後半では、クラス加重を使用してこの問題に対処します。

学習セット、検証セット、およびテスト セットの準備

Deeplab v3+ の学習には、データセットのイメージの 60% が使用されます。残りのイメージは均等に 20% ずつに分割され、検証とテストにそれぞれ 20% が使用されます。次のコードでは、イメージとピクセル ラベル データを学習セット、検証セット、およびテスト セットに無作為に分割します。

[imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = partitionCamVidData(imds,pxds);

60 対 20 対 20 に分割すると、学習イメージ、検証イメージ、およびテスト イメージの数が次のようになります。

numTrainingImages = numel(imdsTrain.Files)
numTrainingImages = 421
numValImages = numel(imdsVal.Files)
numValImages = 140
numTestingImages = numel(imdsTest.Files)
numTestingImages = 140

検証データを定義します。

dsVal = combine(imdsVal,pxdsVal);

データ拡張

データ拡張は、学習中に元のデータをランダムに変換してネットワークの精度を高めるために使用されます。データ拡張を使用すると、ラベル付き学習サンプルの数を増やさずに、学習データをさらに多様化させることができます。イメージとピクセル ラベル データの両方に同じランダム変換を適用するには、データストアに combinetransform を使用します。まず、imdsTrainpxdsTrain を統合します。

dsTrain = combine(imdsTrain,pxdsTrain);

次に、データストアに transform を使用して、サポート関数 augmentImageAndLabel で定義されている目的のデータ拡張を適用します。ここでは、データ拡張に対して +/- 10 ピクセルのランダムな左/右反射とランダムな X/Y 平行移動が使用されます。

xTrans = [-10 10];
yTrans = [-10 10];
dsTrain = transform(dsTrain, @(data)augmentImageAndLabel(data,xTrans,yTrans));

データ拡張は、テスト データと検証データには適用されないことに注意してください。理想的には、テスト データと検証データは元のデータを代表するもので、バイアスのない評価を行うために変更なしで使用されなければなりません。

ネットワークの作成

ネットワークのイメージ サイズを指定します。これは通常、学習時のイメージ サイズと同じです。

imageSize = [720 960 3];

クラス数を指定します。

numClasses = numel(classes);

関数 deeplabv3plus を使用して、ResNet-18 に基づいて DeepLab v3+ ネットワークを作成します。用途に最適なネットワークを選択することは、経験的解析が必要であり、別のレベルのハイパーパラメーター調整です。たとえば、ResNet-50 や MobileNet v2 などの異なる基本ネットワークを試すか、または U-Net などの別のセマンティック セグメンテーション ネットワーク アーキテクチャを試すことができます。

network = deeplabv3plus(imageSize,numClasses,"resnet18");

クラス加重を使用したクラスのバランス調整

前に示したように、CamVid 内のクラスはバランスがとれていません。学習を改善するために、クラス加重を使用してクラスのバランスを調整することができます。前に関数countEachLabel (Computer Vision Toolbox)で計算したピクセル ラベルのカウントを使用して、中央頻度クラス加重を計算します。

imageFreq = tbl.PixelCount ./ tbl.ImagePixelCount;
classWeights = median(imageFreq) ./ imageFreq;

学習オプションの選択

学習に使用される最適化アルゴリズムはモーメンタム項付き確率的勾配降下法 (SGDM) です。trainingOptions を使用して、SGDM に使用されるハイパーパラメーターを指定します。

学習率には区分的なスケジュールが使用されます。学習率は 6 エポックごとに 0.1 倍に減少します。これにより、ネットワークはより高い初期学習率で高速に学習することができる一方で、学習率が低下すると、局所的最適値に近い解を求めることができます。

名前と値の引数 ValidationData を設定することによって、すべてのエポックで検証データに対してネットワークのテストが行われます。ValidationPatience は 4 に設定されており、検証精度が収束すると学習が早期に停止します。これにより、学習データセットに対するネットワークの過適合を防ぎます。

ミニバッチのサイズ 4 を使用して、学習中のメモリ使用量を削減します。この値は、システムに搭載されている GPU メモリの量に応じて増減させることができます。

また、CheckpointPath は一時的な場所に設定されています。この名前と値の引数を指定すると、各学習エポックの終わりにネットワーク チェックポイントを保存できます。システム障害や停電で学習が中断された場合に、保存したチェックポイントから学習を再開できます。CheckpointPath で指定された場所に、ネットワーク チェックポイントを保存するのに十分なスペースがあることを確認します。たとえば、100 個の Deeplab v3+ チェックポイントを保存する場合、各チェックポイントが 61 MB であるため、約 6 GB のディスク領域が必要です。

options = trainingOptions("sgdm",...
    LearnRateSchedule="piecewise",...
    LearnRateDropPeriod=6,...
    LearnRateDropFactor=0.1,...
    Momentum=0.9,...
    InitialLearnRate=1e-2,...
    L2Regularization=0.005,...
    ValidationData=dsVal,...
    MaxEpochs=18,...  
    MiniBatchSize=4,...
    Shuffle="every-epoch",...
    CheckpointPath=tempdir,...
    VerboseFrequency=10,...
    ValidationPatience=4);

学習の開始

ネットワークに学習させるには、次のコードで変数 doTrainingtrue に設定します。関数trainnetを使用してニューラル ネットワークに学習させます。補助関数 modelLoss によって指定されたカスタム損失関数を使用します。既定では、関数 trainnet は利用可能な GPU がある場合にそれを使用します。GPU での学習には、Parallel Computing Toolbox™ ライセンスとサポートされている GPU デバイスが必要です。サポートされているデバイスについては、GPU 計算の要件 (Parallel Computing Toolbox)を参照してください。そうでない場合、関数 trainnet は CPU を使用します。実行環境を指定するには、ExecutionEnvironment 学習オプションを使用します。

メモ: この学習は、24 GB メモリ搭載の NVIDIA™ GeForce RTX 3090 Ti で検証しました。GPU のメモリがこれより少ない場合、学習時にメモリ不足が発生する可能性があります。これが発生する場合は、trainingOptionsMiniBatchSize を 1 に設定するか、ネットワーク入力サイズを減らして学習データのサイズを変更してみてください。このネットワークに学習させるには、約 50 分かかります。GPU ハードウェアによっては、さらに時間がかかる場合があります。

doTraining = false;
if doTraining
    [net,info] = trainnet(dsTrain,network,@(Y,T) modelLoss(Y,T,classWeights),options);
end

1 つのイメージを使用したネットワーク テスト

1 つのテスト イメージで学習させたネットワークを実行します。

I = readimage(imdsTest,35);
C = semanticseg(I,net,Classes=classes);

結果を表示します。

B = labeloverlay(I,C,Colormap=cmap,Transparency=0.4);
imshow(B)
pixelLabelColorbar(cmap, classes);

C での結果と、pxdsTest に格納されている予想されるグラウンド トゥルースを比較します。緑とマゼンタの領域は、セグメンテーション結果が予想されるグラウンド トゥルースと異なる領域を強調表示しています。

expectedResult = readimage(pxdsTest,35);
actual = uint8(C);
expected = uint8(expectedResult);
imshowpair(actual, expected)

視覚的には、道路、空、木、建物などのクラスのセマンティック セグメンテーションの結果は適切にオーバーラップしています。しかし、歩行者や車のような小さいオブジェクトはそれほど正確ではありません。クラスごとのオーバーラップ量は、ジャカード インデックスとしても知られている Intersection over Union (IoU) メトリクスを使用して測定できます。関数jaccard (Image Processing Toolbox)を使用して IoU を測定します。

iou = jaccard(C,expectedResult);
table(classes,iou)
ans=11×2 table
      classes         iou  
    ____________    _______

    "Sky"           0.93632
    "Building"      0.87723
    "Pole"          0.40475
    "Road"          0.95332
    "Pavement"       0.8558
    "Tree"          0.92632
    "SignSymbol"    0.62978
    "Fence"         0.82389
    "Car"           0.75381
    "Pedestrian"    0.26717
    "Bicyclist"      0.7058

IoU メトリクスでは視覚的な結果を確認できます。道路、空、木、建物クラスの IoU スコアは高く、一方で歩行者や自動車などのクラスのスコアは低くなります。その他の一般的なセグメンテーション メトリクスには、dice (Image Processing Toolbox)bfscore (Image Processing Toolbox) の輪郭マッチング スコアなどがあります。

学習済みネットワークの評価

複数のテスト イメージの精度を測定するには、テスト セット全体に対して semanticseg (Computer Vision Toolbox) を実行します。ミニバッチのサイズ 4 を使用して、イメージのセグメント化中のメモリ使用量を削減します。この値は、システムに搭載されている GPU メモリの量に応じて増減させることができます。

pxdsResults = semanticseg(imdsTest,net, ...
    Classes=classes, ...
    MiniBatchSize=4, ...
    WriteLocation=tempdir, ...
    Verbose=false);

semanticseg はテスト セットに対する結果を pixelLabelDatastore オブジェクトとして返します。imdsTest 内の各テスト イメージの実際のピクセル ラベル データは、名前と値の引数 WriteLocation で指定された場所にあるディスクに書き込まれます。evaluateSemanticSegmentation (Computer Vision Toolbox)を使用して、テスト セット結果のセマンティック セグメンテーション メトリクスを測定します。

metrics = evaluateSemanticSegmentation(pxdsResults,pxdsTest,Verbose=false);

evaluateSemanticSegmentation は、データセット全体、個々のクラス、各テスト イメージに関するさまざまなメトリクスを返します。データセット レベルのメトリクスを確認するには、metrics.DataSetMetrics を検査します。データセット メトリクスは、ネットワーク パフォーマンスに関する大まかな概要を示します。

metrics.DataSetMetrics
ans=1×5 table
    GlobalAccuracy    MeanAccuracy    MeanIoU    WeightedIoU    MeanBFScore
    ______________    ____________    _______    ___________    ___________

       0.90748          0.88828       0.69573      0.84904        0.74304  

各クラスがパフォーマンス全体に与える影響を確認するには、metrics.ClassMetrics を使用してクラスごとのメトリクスを検査します。

データセット全体のパフォーマンスは非常に高いですが、クラス メトリクスは、PedestrianBicyclistCar といった少数しか存在しないクラスが RoadSkyTreeBuilding などのクラスと同じようにうまくセグメント化されていないことを示しています。少数しか存在しないクラスのサンプルが多く含まれているデータが追加されることで、結果が改善する可能性があります。

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

    Sky            0.9438     0.91456      0.91326  
    Building      0.84484     0.82403      0.69502  
    Pole          0.82513     0.29465      0.65171  
    Road          0.94803     0.93847      0.84376  
    Pavement      0.92135     0.77639      0.80391  
    Tree          0.89106     0.79122      0.76429  
    SignSymbol    0.81774     0.49374       0.5954  
    Fence         0.81991      0.6213      0.63421  
    Car           0.93654      0.8163       0.7784  
    Pedestrian    0.91095     0.50498      0.69317  
    Bicyclist     0.91172     0.67738      0.72119  

サポート関数

function labelIDs = camvidPixelLabelIDs()
% Return the label IDs corresponding to each class.
%
% The CamVid dataset has 32 classes. Group them into 11 classes following
% the original SegNet training methodology [1].
%
% The 11 classes are:
%   "Sky" "Building", "Pole", "Road", "Pavement", "Tree", "SignSymbol",
%   "Fence", "Car", "Pedestrian",  and "Bicyclist".
%
% CamVid pixel label IDs are provided as RGB color values. Group them into
% 11 classes and return them as a cell array of M-by-3 matrices. The
% original CamVid class names are listed alongside each RGB value. Note
% that the Other/Void class are excluded below.
labelIDs = { ...
    
    % "Sky"
    [
    128 128 128; ... % "Sky"
    ]
    
    % "Building" 
    [
    000 128 064; ... % "Bridge"
    128 000 000; ... % "Building"
    064 192 000; ... % "Wall"
    064 000 064; ... % "Tunnel"
    192 000 128; ... % "Archway"
    ]
    
    % "Pole"
    [
    192 192 128; ... % "Column_Pole"
    000 000 064; ... % "TrafficCone"
    ]
    
    % Road
    [
    128 064 128; ... % "Road"
    128 000 192; ... % "LaneMkgsDriv"
    192 000 064; ... % "LaneMkgsNonDriv"
    ]
    
    % "Pavement"
    [
    000 000 192; ... % "Sidewalk" 
    064 192 128; ... % "ParkingBlock"
    128 128 192; ... % "RoadShoulder"
    ]
        
    % "Tree"
    [
    128 128 000; ... % "Tree"
    192 192 000; ... % "VegetationMisc"
    ]
    
    % "SignSymbol"
    [
    192 128 128; ... % "SignSymbol"
    128 128 064; ... % "Misc_Text"
    000 064 064; ... % "TrafficLight"
    ]
    
    % "Fence"
    [
    064 064 128; ... % "Fence"
    ]
    
    % "Car"
    [
    064 000 128; ... % "Car"
    064 128 192; ... % "SUVPickupTruck"
    192 128 192; ... % "Truck_Bus"
    192 064 128; ... % "Train"
    128 064 064; ... % "OtherMoving"
    ]
    
    % "Pedestrian"
    [
    064 064 000; ... % "Pedestrian"
    192 128 064; ... % "Child"
    064 000 192; ... % "CartLuggagePram"
    064 128 064; ... % "Animal"
    ]
    
    % "Bicyclist"
    [
    000 128 192; ... % "Bicyclist"
    192 000 192; ... % "MotorcycleScooter"
    ]
    
    };
end
function classes = getClassNames()
classes = [
    "Sky"
    "Building"
    "Pole"
    "Road"
    "Pavement"
    "Tree"
    "SignSymbol"
    "Fence"
    "Car"
    "Pedestrian"
    "Bicyclist"
    ];
end
function pixelLabelColorbar(cmap, classNames)
% Add a colorbar to the current axis. The colorbar is formatted
% to display the class names with the color.

colormap(gca,cmap)

% Add colorbar to current figure.
c = colorbar('peer', gca);

% Use class names for tick marks.
c.TickLabels = classNames;
numClasses = size(cmap,1);

% Center tick labels.
c.Ticks = 1/(numClasses*2):1/numClasses:1;

% Remove tick mark.
c.TickLength = 0;
end
function cmap = camvidColorMap()
% Define the colormap used by CamVid dataset.

cmap = [
    128 128 128   % Sky
    128 0 0       % Building
    192 192 192   % Pole
    128 64 128    % Road
    60 40 222     % Pavement
    128 128 0     % Tree
    192 128 128   % SignSymbol
    64 64 128     % Fence
    64 0 128      % Car
    64 64 0       % Pedestrian
    0 128 192     % Bicyclist
    ];

% Normalize between [0 1].
cmap = cmap ./ 255;
end
function [imdsTrain, imdsVal, imdsTest, pxdsTrain, pxdsVal, pxdsTest] = partitionCamVidData(imds,pxds)
% Partition CamVid data by randomly selecting 60% of the data for training. The
% rest is used for testing.
    
% Set initial random state for example reproducibility.
rng(0); 
numFiles = numpartitions(imds);
shuffledIndices = randperm(numFiles);

% Use 60% of the images for training.
numTrain = round(0.60 * numFiles);
trainingIdx = shuffledIndices(1:numTrain);

% Use 20% of the images for validation
numVal = round(0.20 * numFiles);
valIdx = shuffledIndices(numTrain+1:numTrain+numVal);

% Use the rest for testing.
testIdx = shuffledIndices(numTrain+numVal+1:end);

% Create image datastores for training and test.
imdsTrain = subset(imds,trainingIdx);
imdsVal = subset(imds,valIdx);
imdsTest = subset(imds,testIdx);

% Create pixel label datastores for training and test.
pxdsTrain = subset(pxds,trainingIdx);
pxdsVal = subset(pxds,valIdx);
pxdsTest = subset(pxds,testIdx);
end
function data = augmentImageAndLabel(data, xTrans, yTrans)
% Augment images and pixel label images using random reflection and
% translation.

for i = 1:size(data,1)
    
    tform = randomAffine2d(...
        XReflection=true,...
        XTranslation=xTrans, ...
        YTranslation=yTrans);
    
    % Center the view at the center of image in the output space while
    % allowing translation to move the output image out of view.
    rout = affineOutputView(size(data{i,1}), tform, BoundsStyle='centerOutput');
    
    % Warp the image and pixel labels using the same transform.
    data{i,1} = imwarp(data{i,1}, tform, OutputView=rout);
    data{i,2} = imwarp(data{i,2}, tform, OutputView=rout);
    
end
end
function loss = modelLoss(Y,T,classWeights)
    weights = dlarray(classWeights,"C");
    mask = ~isnan(T);
    T(isnan(T)) = 0;
    loss = crossentropy(Y,T,weights,Mask=mask,NormalizationFactor="mask-included");
end

参考文献

[1] Chen, Liang-Chieh et al. "Encoder-Decoder with Atrous Separable Convolution for Semantic Image Segmentation." ECCV (2018).

[2] Brostow, G. J., J. Fauqueur, and R. Cipolla. "Semantic object classes in video: A high-definition ground truth database." Pattern Recognition Letters. Vol. 30, Issue 2, 2009, pp 88-97.

参考

(Computer Vision Toolbox) | (Computer Vision Toolbox) | (Image Processing Toolbox) | (Computer Vision Toolbox) | | | | | (Computer Vision Toolbox)

関連するトピック