이 페이지의 최신 내용은 아직 번역되지 않았습니다. 최신 내용은 영문으로 볼 수 있습니다.

심층 학습을 사용한 의미론적 분할

이 예제에서는 심층 학습을 사용하여 의미론적 분할 네트워크를 훈련시키는 방법을 보여줍니다.

의미론적 분할 네트워크는 이미지의 모든 픽셀을 분류하여 클래스별로 분할된 이미지를 산출합니다. 의미론적 분할의 응용 분야에는 자율 주행을 위한 도로 분할, 의료 진단을 위한 암 세포 분할 등이 있습니다. 자세한 내용은 Getting Started With Semantic Segmentation Using Deep Learning (Computer Vision Toolbox) 항목을 참조하십시오.

훈련 과정을 보여주기 위해 이 예제에서는 의미론적 이미지 분할을 위해 설계된 CNN(컨벌루션 신경망)의 일종인 Deeplab v3+ [1]를 훈련시킵니다. 의미론적 분할을 위한 네트워크에는 그 밖에도 FCN(완전 컨벌루션 네트워크), SegNet 및 U-Net이 있습니다. 여기에서 설명하는 훈련 과정은 이러한 네트워크에도 적용할 수 있습니다.

이 예제에서는 훈련을 위해 University of Cambridge의 CamVid 데이터셋 [2]을 사용합니다. 이 데이터셋은 주행하면서 얻은 거리 수준 뷰가 들어있는 이미지 모음입니다. 이 데이터셋은 자동차, 보행자, 도로를 비롯한 32개의 의미론적 클래스에 대해 픽셀 수준의 레이블을 제공합니다.

설치

이 예제에서는 사전 훈련된 Resnet-18 네트워크로부터 초기화된 가중치를 사용하여 Deeplab v3+ 네트워크를 만듭니다. ResNet-18은 처리 리소스가 한정적인 응용 사례에 적합한 효율적인 네트워크입니다. 응용 사례의 요구 사항에 따라 MobileNet v2나 ResNet-50과 같은 여타 사전 훈련된 네트워크도 사용할 수 있습니다. 자세한 내용은 사전 훈련된 심층 신경망 항목을 참조하십시오.

사전 훈련된 Resnet-18을 받으려면 Deep Learning Toolbox™ Model for Resnet-18 Network를 설치하십시오. 설치가 완료되면 다음 코드를 실행하여 올바르게 설치되었는지 확인합니다.

resnet18();

또한 DeepLab v3+의 사전 훈련된 버전을 다운로드합니다. 사전 훈련된 모델을 사용하면 훈련이 완료될 때까지 기다리지 않고 전체 예제를 실행할 수 있습니다.

pretrainedURL = 'https://www.mathworks.com/supportfiles/vision/data/deeplabv3plusResnet18CamVid.mat';
pretrainedFolder = fullfile(tempdir,'pretrainedNetwork');
pretrainedNetwork = fullfile(pretrainedFolder,'deeplabv3plusResnet18CamVid.mat'); 
if ~exist(pretrainedFolder,'dir')
    mkdir(pretrainedFolder);
    disp('Downloading pretrained network (58 MB)...');
    websave(pretrainedNetwork,pretrainedURL);
end

이 예제를 실행할 때는 CUDA 지원 NVIDIA™ GPU(Compute Capability 3.0 이상)를 사용하는 것이 권장됩니다. GPU를 사용하려면 Parallel Computing Toolbox™가 필요합니다.

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'); 

if ~exist(outputFolder, 'dir')
   
    mkdir(outputFolder)
    labelsZip = fullfile(outputFolder,'labels.zip');
    imagesZip = fullfile(outputFolder,'images.zip');   
    
    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

참고: 데이터 다운로드에 걸리는 시간은 인터넷 연결에 따라 달라집니다. 위에서 사용한 명령은 다운로드가 완료될 때까지 MATLAB을 차단합니다. 또는 웹 브라우저를 사용하여 먼저 로컬 디스크에 데이터셋을 다운로드할 수도 있습니다. 웹에서 다운로드한 파일을 사용하려면 위에서 outputFolder 변수를 다운로드한 파일의 위치로 변경하십시오.

CamVid 이미지 불러오기

imageDatastore를 사용하여 CamVid 이미지를 불러옵니다. imageDatastore를 사용하면 대규모의 이미지 모음을 디스크에 효율적으로 불러올 수 있습니다.

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

이미지 하나를 표시합니다.

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

픽셀에 레이블이 지정된 CamVid 이미지 불러오기

pixelLabelDatastore를 사용하여 픽셀에 레이블이 지정된 CamVid 이미지 데이터를 불러옵니다. pixelLabelDatastore는 픽셀 레이블 데이터와 레이블 ID를 클래스 이름 매핑으로 캡슐화합니다.

훈련을 보다 쉽게 하기 위해 CamVid에 포함된 32개의 원본 클래스를 11개의 클래스로 그룹화합니다. 이러한 클래스를 지정합니다.

classes = [
    "Sky"
    "Building"
    "Pole"
    "Road"
    "Pavement"
    "Tree"
    "SignSymbol"
    "Fence"
    "Car"
    "Pedestrian"
    "Bicyclist"
    ];

32개의 클래스를 11개로 줄이기 위해 원본 데이터셋의 여러 클래스가 하나로 그룹화됩니다. 예를 들어, "Car", "SUVPickupTruck", "Truck_Bus", "Train", "OtherMoving"이 모두 "Car"로 그룹화됩니다. 그룹화된 레이블 ID를 지원 함수 camvidPixelLabelIDs(이 예제의 마지막에 나열되어 있음)를 사용하여 반환합니다.

labelIDs = camvidPixelLabelIDs();

클래스와 레이블 ID를 사용하여 pixelLabelDatastore.를 만듭니다.

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

픽셀에 레이블이 지정된 이미지 중 하나를 읽어 들이고 이미지 위에 중첩하여 표시합니다.

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

색 중첩이 없는 영역은 픽셀 레이블을 갖지 않으며 훈련 중에 사용되지 않습니다.

데이터셋 통계량 분석하기

CamVid 데이터셋의 클래스 레이블의 분포를 보려면 countEachLabel을 사용하십시오. 이 함수는 클래스 레이블을 기준으로 픽셀 개수를 셉니다.

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에 포함된 클래스 간에 균형이 맞지 않습니다. 이것은 거리 장면으로 구성된 자동차 데이터 세트에서 일반적으로 나타나는 문제입니다. 이러한 장면에서는 하늘과 건물, 도로가 이미지에서 더 많은 영역을 차지하기 때문에 보행자, 자전거 운전자의 픽셀보다 하늘, 건물, 도로의 픽셀이 더 많습니다. 이러한 불균형을 올바르게 처리하지 않으면 비중이 더 큰 클래스로 인해 학습에 편향이 발생하여 학습을 저해할 수 있습니다. 이 예제의 뒷부분에서 클래스 가중치를 사용하여 이 문제를 처리합니다.

CamVid 데이터 세트의 이미지 크기는 720x960입니다. 이미지 크기는 12GB 메모리가 탑재된 NVIDIA™ Titan X에서 상당히 큰 크기의 이미지 배치가 메모리에 담길 수 있도록 선택되었습니다. GPU에 충분한 메모리가 없으면 이미지를 더 작은 크기로 조정하거나 훈련 일괄 처리 작업을 줄여야 할 수 있습니다.

훈련 세트, 검증 세트와 테스트 세트 준비하기

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

네트워크 만들기

이 예제에 지원 파일로 첨부되어 있는 helperDeeplabv3PlusResnet18 함수를 사용하여 ResNet-18을 기반으로 하는 DeepLab v3+ 네트워크를 만듭니다. 응용 사례에 가장 적합한 네트워크를 선택하려면 경험적 분석이 필요하며 이것은 또 다른 수준의 하이퍼파라미터 조정이 됩니다. 예를 들어, ResNet-50이나 Inception v3과 같은 다른 기본 네트워크로 실험해 보거나 SegNet, FCN(완전 컨벌루션 네트워크) 또는 U-Net과 같은 다른 의미론적 분할 네트워크 아키텍처를 사용해 볼 수 있습니다.

% Specify the network image size. This is typically the same as the traing image sizes.
imageSize = [720 960 3];

% Specify the number of classes.
numClasses = numel(classes);

% Create DeepLab v3+.
lgraph = helperDeeplabv3PlusResnet18(imageSize, numClasses);

클래스 가중치를 사용하여 클래스 간의 균형 맞추기

앞에서 보았듯이 CamVid는 클래스 간에 균형이 맞지 않습니다. 훈련의 향상을 위해 클래스 가중치를 사용하여 클래스 간의 균형을 맞출 수 있습니다. 앞부분에서 countEachLabel로 계산한 픽셀 레이블 개수를 사용하여 중앙값 빈도 클래스 가중치를 계산합니다.

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

    0.3182
    0.2082
    5.0924
    0.1744
    0.7103
    0.4175
    4.5371
    1.8386
    1.0000
    6.6059
      ⋮

pixelClassificationLayer를 사용하여 클래스 가중치를 지정합니다.

pxLayer = pixelClassificationLayer('Name','labels','Classes',tbl.Name,'ClassWeights',classWeights);
lgraph = replaceLayer(lgraph,"classification",pxLayer);

훈련 옵션 선택하기

훈련에 사용되는 최적화 알고리즘은 SGDM(모멘텀을 사용한 확률적 경사하강법)입니다. trainingOptions를 사용하여 SGDM에 사용할 하이퍼파라미터를 지정합니다.

% Define validation data.
pximdsVal = pixelLabelImageDatastore(imdsVal,pxdsVal);

% Define training options. 
options = trainingOptions('sgdm', ...
    'LearnRateSchedule','piecewise',...
    'LearnRateDropPeriod',10,...
    'LearnRateDropFactor',0.3,...
    'Momentum',0.9, ...
    'InitialLearnRate',1e-3, ...
    'L2Regularization',0.005, ...
    'ValidationData',pximdsVal,...
    'MaxEpochs',30, ...  
    'MiniBatchSize',8, ...
    'Shuffle','every-epoch', ...
    'CheckpointPath', tempdir, ...
    'VerboseFrequency',2,...
    'Plots','training-progress',...
    'ValidationPatience', 4); ...

학습률은 조각별 스케줄을 사용합니다. Epoch 10회마다 학습률이 0.3배만큼 줄어듭니다. 이렇게 하면 네트워크가 더 높은 초기 학습률로 빠르게 학습할 수 있으면서도 학습률이 떨어지기 시작하면 국소 최적해에 가까운 해를 구할 수 있습니다.

'ValidationData' 파라미터를 설정함으로써 네트워크가 매 Epoch마다 검증 데이터에 테스트됩니다. 'ValidationPatience'는 검증 정확도가 수렴하면 훈련이 조기에 중지되도록 4로 설정되었습니다. 이렇게 하면 네트워크가 훈련 데이터셋에 대해 과적합되는 것이 방지됩니다.

훈련 중에 사용되는 메모리를 줄이기 위해 미니 배치의 크기는 8을 사용합니다. 시스템의 GPU 메모리 양에 따라 이 값을 늘리거나 줄일 수 있습니다.

또한 'CheckpointPath'가 임시 위치로 설정됩니다. 이 이름-값 쌍을 사용하면 매 훈련 Epoch가 끝날 때마다 네트워크 검사 지점을 저장할 수 있습니다. 시스템 장애나 정전으로 인해 훈련이 중단된 경우, 저장된 검사 지점에서 훈련을 재개할 수 있습니다. 'CheckpointPath'로 지정하는 위치에 네트워크 검사 지점을 저장할 수 있을 만큼 충분한 공간이 있는지 확인하십시오. 예를 들어, 각 Deeplab v3+ 검사 지점은 61MB이므로 검사 지점을 100개 저장하려면 약 6GB의 디스크 공간이 필요합니다.

데이터 증대

데이터 증대는 네트워크의 정확도를 높이는 데 도움이 됩니다. 따라서 네트워크에 더 많은 표본을 제공하기 위해 훈련 중에 데이터 증대가 사용됩니다. 여기서는 데이터 증대를 위해 무작위 좌우 반사와 +/- 10개 픽셀의 X/Y 무작위 평행 이동을 사용합니다. imageDataAugmenter를 사용하여 이러한 데이터 증대 파라미터를 지정합니다.

augmenter = imageDataAugmenter('RandXReflection',true,...
    'RandXTranslation',[-10 10],'RandYTranslation',[-10 10]);

imageDataAugmenter는 이 밖에도 몇 가지 유형의 데이터 증대를 지원합니다. 다른 유형의 데이터 증대를 선택하려면 경험적 분석이 필요하며, 이것은 또 다른 수준의 하이퍼파라미터 조정이 됩니다.

훈련 시작하기

pixelLabelImageDatastore를 사용하여 훈련 데이터와 데이터 증대 선택 사항을 결합합니다. pixelLabelImageDatastore는 훈련 데이터 배치를 읽어 들이고, 데이터 증대를 적용하고, 증대된 데이터를 훈련 알고리즘으로 보냅니다.

pximds = pixelLabelImageDatastore(imdsTrain,pxdsTrain, ...
    'DataAugmentation',augmenter);

doTraining 플래그가 true이면 trainNetwork를 사용하여 훈련을 시작합니다. 그렇지 않으면 사전 훈련된 네트워크를 불러오십시오.

참고: 이 훈련은 12GB의 GPU 메모리가 탑재된 NVIDIA™ Titan X에서 검증되었습니다. GPU 메모리가 이보다 적으면 메모리 부족이 발생할 수 있습니다. 메모리 부족이 발생하면 trainingOptions에서 'MiniBatchSize'를 1로 설정해 보십시오. 이 네트워크를 훈련시키는 데는 약 5시간이 걸립니다. GPU 하드웨어에 따라 시간이 더 걸릴 수 있습니다.

doTraining = false;
if doTraining    
    [net, info] = trainNetwork(pximds,lgraph,options);
else
    data = load(pretrainedNetwork); 
    net = data.net;
end

한 개 이미지로 네트워크 테스트하기

간단히 확인하기 위해 훈련된 네트워크를 한 개의 테스트 이미지에 대해 실행합니다.

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

결과를 표시합니다.

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)

의미론적 분할 결과가 도로, 하늘, 건물에 대해 잘 중첩되는 것을 볼 수 있습니다. 그러나 보행자, 자동차와 같이 상대적으로 크기가 작은 사물은 그만큼 정확하지 않습니다. 각 클래스마다 중첩되는 정도는 Jaccard 지수라고도 부르는 IoU(intersection-over-union) 메트릭을 사용하여 측정할 수 있습니다. jaccard 함수를 사용하여 IoU를 측정합니다.

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

    "Sky"           0.91837
    "Building"      0.84479
    "Pole"          0.31203
    "Road"          0.93698
    "Pavement"      0.82838
    "Tree"          0.89636
    "SignSymbol"    0.57644
    "Fence"         0.71046
    "Car"           0.66688
    "Pedestrian"    0.48417
    "Bicyclist"     0.68431

IoU 메트릭을 통해 시각적 결과를 확인할 수 있습니다. 도로, 하늘, 건물 클래스는 IoU 점수가 높고 보행자, 자동차 클래스는 IoU 점수가 낮습니다. 그 밖에 널리 사용되는 분할 메트릭에는 dicebfscore 윤곽선 일치 점수가 있습니다.

훈련된 네트워크 평가하기

여러 테스트 이미지에 대한 정확도를 측정하려면 전체 테스트 세트에 대해 semanticseg를 실행하십시오. 이미지 분할 시 사용되는 메모리를 줄이기 위해 미니 배치의 크기는 4를 사용합니다. 시스템의 GPU 메모리 양에 따라 이 값을 늘리거나 줄일 수 있습니다.

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

semanticseg는 테스트 세트에 대한 결과를 pixelLabelDatastore 객체로 반환합니다. imdsTest의 각 테스트 이미지에 대한 실제 픽셀 레이블 데이터는 'WriteLocation' 파라미터로 지정된 위치에 있는 디스크에 쓰입니다. evaluateSemanticSegmentation을 사용하여 테스트 세트 결과에 대한 의미론적 분할 메트릭을 측정합니다.

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

evaluateSemanticSegmentation은 전체 데이터셋, 개별 클래스 및 각 테스트 이미지에 대한 다양한 메트릭을 반환합니다. 데이터셋 수준 메트릭을 보려면 metrics.DataSetMetrics를 조사하십시오.

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

       0.87695          0.85392       0.6302       0.80851        0.65051  

데이터셋 메트릭은 네트워크 성능에 대한 개요를 제공합니다. 각 클래스가 전체 성능에 미치는 영향을 보려면 metrics.ClassMetrics를 사용하여 클래스별 메트릭을 조사하십시오.

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

    Sky           0.93111     0.90209       0.8952  
    Building      0.78453     0.76098      0.58511  
    Pole          0.71586     0.21477       0.5144  
    Road          0.93024     0.91465      0.76696  
    Pavement      0.88466     0.70571      0.70919  
    Tree          0.87377     0.76323      0.70875  
    SignSymbol    0.79358     0.39309      0.48302  
    Fence         0.81507     0.46484      0.48565  
    Car           0.90956     0.76799      0.69233  
    Pedestrian    0.87629      0.4366      0.60792  
    Bicyclist     0.87844     0.60829      0.55089  

전반적인 데이터셋 성능은 꽤 우수하지만, 클래스 메트릭을 보면 Pedestrian, Bicyclist, Car처럼 부족하게 표시되었던 클래스는 Road, Sky, Building 같은 클래스만큼 잘 분할되지 않았음을 알 수 있습니다. 부족하게 표시되었던 클래스의 샘플을 더 많이 포함한 데이터를 추가하면 결과가 개선될 수 있습니다.

지원 함수

helperDeeplabv3PlusResnet18.m은 이 예제에 지원 파일로 첨부되어 있습니다.

% lgraph = helperDeeplabv3PlusResnet18(imageSize, numClasses) creates a
% DeepLab v3+ layer graph object using a pre-trained ResNet-18 configured
% using the following inputs:
%
%   Inputs
%   ------
%   imageSize    - size of the network input image specified as a vector
%                  [H W] or [H W C], where H and W are the image height and
%                  width, and C is the number of image channels.
%
%   numClasses   - number of classes the network should be configured to
%                  classify.
%
% The output lgraph is a LayerGraph object.
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 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 = numel(imds.Files);
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.
trainingImages = imds.Files(trainingIdx);
valImages = imds.Files(valIdx);
testImages = imds.Files(testIdx);

imdsTrain = imageDatastore(trainingImages);
imdsVal = imageDatastore(valImages);
imdsTest = imageDatastore(testImages);

% Extract class and label IDs info.
classes = pxds.ClassNames;
labelIDs = camvidPixelLabelIDs();

% Create pixel label datastores for training and test.
trainingLabels = pxds.Files(trainingIdx);
valLabels = pxds.Files(valIdx);
testLabels = pxds.Files(testIdx);

pxdsTrain = pixelLabelDatastore(trainingLabels, classes, labelIDs);
pxdsVal = pixelLabelDatastore(valLabels, classes, labelIDs);
pxdsTest = pixelLabelDatastore(testLabels, classes, labelIDs);
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.

참고 항목

| | | | | | | | | |

관련 항목