Main Content

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

U-Net を使用する Intel CPU でのセマンティック セグメンテーション アプリケーションのコード生成

この例では、深層学習を使用するイメージ セグメンテーション アプリケーションのコード生成を示します。codegen コマンドを使用して、イメージ セグメンテーション用の深層学習ネットワーク U-Net を使用して予測を実行する MEX 関数を生成します。

U-Net を使用したイメージのセグメンテーションを codegen コマンドを使用せずに示す類似例については、深層学習を使用したマルチスペクトル イメージのセマンティック セグメンテーション (Image Processing Toolbox)を参照してください。

サードパーティの前提条件

  • Intel Advanced Vector Extensions 2 (Intel AVX2) 手順をサポートする Xeon プロセッサ

この例は、Linux®、Windows® および macOS プラットフォームでサポートされています。

この例では、MATLAB に付属の Intel MKL-DNN ライブラリを使用してセマンティック セグメンテーション用の MEX 関数を生成します。

この例は MATLAB Online ではサポートされていません。

U-Net の概要

U-Net [1] は畳み込みニューラル ネットワーク (CNN) の一種で、セマンティック イメージ セグメンテーション用に設計されています。U-Net では、最初の一連の畳み込み層に最大プーリング層が点在し、入力イメージの解像度を逐次下げていきます。これらの層に、一連の畳み込み層が続き、その中にアップサンプリング演算子が点在し、入力イメージの解像度を逐次上げていきます。これらの 2 つの一連の経路を組み合わせると U 字型の図が形成されます。このネットワークは、元は生物医学のイメージ セグメンテーション アプリケーションで予測を実行するために学習が行われていました。この例は、このネットワークで時間の経過に伴う森林被覆の変化を追跡できることを示しています。環境保護機関は、森林伐採を追跡し、地域の環境的生態学的健全性を評価し特定します。

深層学習ベースのセマンティック セグメンテーションにより、高解像度の航空写真から植被を正確に測定できます。課題の 1 つに、視覚的に類似した特性のクラスを切り分けること、たとえば緑のピクセルを草、低木または樹木として区別することがあります。分類の精度を高めるために、一部のデータセットには各ピクセルに関する追加情報を提供するマルチスペクトル イメージが含まれています。たとえば、ハームリン ビーチ州立公園のデータセットでは、クラスをより明確に分離する近赤外チャネルでカラー イメージが補完されています。

この例では、各ピクセルを正しく分類するために、事前学習済みの U-Net ネットワークと共にハームリン ビーチ州立公園のデータ [2] を使用します。

この例で使用する U-Net は、次の 18 クラスに属するピクセルをセグメント化するように学習されています。

0. Other Class/Image Border      7. Picnic Table         14. Grass
1. Road Markings                 8. Black Wood Panel     15. Sand
2. Tree                          9. White Wood Panel     16. Water (Lake)
3. Building                     10. Orange Landing Pad   17. Water (Pond)
4. Vehicle (Car, Truck, or Bus) 11. Water Buoy           18. Asphalt (Parking Lot/Walkway)
5. Person                       12. Rocks
6. Lifeguard Chair              13. Other Vegetation

事前学習済みの U-Net DAG ネットワーク オブジェクトの取得

trainedUnet_url = 'https://www.mathworks.com/supportfiles/vision/data/multispectralUnet.mat';
downloadTrainedUnet(trainedUnet_url,pwd);
Downloading Pre-trained U-net for Hamlin Beach dataset...
This will take several minutes to download...
done.

ld = load("trainedUnet/multispectralUnet.mat");
net = ld.net;

この DAG ネットワークには、畳み込み層、最大プーリング層、深さ連結層、ピクセル分類出力層など、58 個の層が含まれています。深層学習ネットワーク アーキテクチャを対話的に可視化して表示するには、関数analyzeNetwork (Deep Learning Toolbox)を使用します。

%   analyzeNetwork(net);

エントリポイント関数 segmentImageUnet

エントリポイント関数 segmentImageUnet.m は、multispectralUnet.mat ファイルに含まれている multispectralUnet ネットワークを使用して、入力イメージに対して固定サイズのパッチごとにセマンティック セグメンテーションを実行します。この関数は multispectralUnet.mat ファイルから永続変数 mynet にネットワーク オブジェクトを読み込みます。関数は以降の予測呼び出しではこの永続変数を再利用します。

type('segmentImageUnet.m')
%  OUT = segmentImageUnet(IM, PATCHSIZE) returns a semantically segmented
%  image, segmented using the network multispectralUnet. The segmentation
%  is performed over each patch of size PATCHSIZE.
%
% Copyright 2019-2020 The MathWorks, Inc.
function out = segmentImageUnet(im, patchSize)

%#codegen

persistent mynet;

if isempty(mynet)
    mynet = coder.loadDeepLearningNetwork('trainedUnet/multispectralUnet.mat');
end

[height, width, nChannel] = size(im);
patch = coder.nullcopy(zeros([patchSize, nChannel-1]));

% pad image to have dimensions as multiples of patchSize
padSize = zeros(1,2);
padSize(1) = patchSize(1) - mod(height, patchSize(1));
padSize(2) = patchSize(2) - mod(width, patchSize(2));

im_pad = padarray (im, padSize, 0, 'post');
[height_pad, width_pad, ~] = size(im_pad);

out = zeros([size(im_pad,1), size(im_pad,2)], 'uint8');

for i = 1:patchSize(1):height_pad    
    for j =1:patchSize(2):width_pad        
        for p = 1:nChannel-1              
            patch(:,:,p) = squeeze( im_pad( i:i+patchSize(1)-1,...
                                            j:j+patchSize(2)-1,...
                                            p));            
        end
         
        % pass in input
        segmentedLabels = activations(mynet, patch, 'Segmentation-Layer');
        
        % Takes the max of each channel (6 total at this point)
        [~,L] = max(segmentedLabels,[],3);
        patch_seg = uint8(L);
        
        % populate section of output
        out(i:i+patchSize(1)-1, j:j+patchSize(2)-1) = patch_seg;
       
    end
end

% Remove the padding
out = out(1:height, 1:width);

データの準備

ハームリン ビーチ州立公園のデータをダウンロードします。

if ~exist(fullfile(pwd,'data'),'dir')
    url = 'http://www.cis.rit.edu/~rmk6217/rit18_data.mat';
    downloadHamlinBeachMSIData(url,pwd+"/data/");
end
Downloading Hamlin Beach dataset...
This will take several minutes to download...
done.

データを MATLAB に読み込んで確認します。

load(fullfile(pwd,'data','rit18_data','rit18_data.mat'));

% Examine data
whos test_data
  Name           Size                         Bytes  Class     Attributes

  test_data      7x12446x7654            1333663576  uint16              

イメージには 7 個のチャネルがあります。RGB カラー チャネルは 4 番目、5 番目および 6 番目のイメージ チャネルです。最初の 3 つのチャネルは近赤外域に対応し、熱の痕跡に基づいて、イメージの異なる成分を強調表示します。チャネル 7 は有効なセグメンテーション領域を示すマスクです。

マルチスペクトル イメージ データは numChannels x width x height 配列に配置されます。MATLAB では、マルチチャネル イメージは width x height x numChannels 配列に配置されます。チャネルが 3 番目の次元になるようにデータを形状変更するには、補助関数 switchChannelsToThirdPlane を使用します。

test_data  = switchChannelsToThirdPlane(test_data);

データの構造が正しいことを確認します (チャネルが最後に来る)。

whos test_data
  Name               Size                     Bytes  Class     Attributes

  test_data      12446x7654x7            1333663576  uint16              

この例では、変数 test_data に含まれているハームリン ビーチ州立公園の完全なデータセットのトリミング バージョンを使用します。test_data の高さと幅をトリミングして、この例で使用する変数 input_data を作成します。

test_datacropRGB = imcrop(test_data(:,:,1:3),[2600, 3000, 2000, 2000]);
test_datacropInfrared = imcrop(test_data(:,:,4:6),[2600, 3000, 2000, 2000]);
test_datacropMask = imcrop(test_data(:,:,7),[2600, 3000, 2000, 2000]);
input_data(:,:,1:3) = test_datacropRGB;
input_data(:,:,4:6) = test_datacropInfrared;
input_data(:,:,7) = test_datacropMask;

変数 input_data を確認します。

whos('input_data');
  Name               Size                   Bytes  Class     Attributes

  input_data      2001x2001x7            56056014  uint16              

MEX の生成

エントリポイント関数 segmentImageUnet.m の MEX 関数を生成するには、MEX コード生成用のコード構成オブジェクト cfg を作成します。ターゲット言語を C++ に設定します。関数coder.DeepLearningConfig (GPU Coder)を使用して MKL-DNN 深層学習構成オブジェクトを作成し、それを cfgDeepLearningConfig プロパティに割り当てます。入力サイズ [12446,7654,7] とパッチ サイズ [1024,1024] を指定して codegen コマンドを実行します。これらの値は変数 input_data 全体のサイズに対応します。パッチ サイズが小さいと推論が速くなります。パッチの計算方法については、エントリポイント関数 segmentImageUnet を参照してください。

cfg = coder.config('mex');
cfg.TargetLang = 'C++';
cfg.DeepLearningConfig = coder.DeepLearningConfig('mkldnn');
codegen -config cfg segmentImageUnet -args {ones(size(input_data),'uint16'),coder.Constant([1024 1024])} -report
Code generation successful: To view the report, open('codegen\mex\segmentImageUnet\html\report.mldatx').

生成された MEX の実行による input_data の結果の予測

関数 segmentImageUnet は、input_data とパッチ サイズの次元を含むベクトルを入力として受け入れます。この関数はイメージをパッチに分割し、特定のパッチ内のピクセルを予測して、最後にすべてのパッチを結合します。input_data のサイズが大きいため (12446 x 7654 x 7)、イメージはパッチで処理する方が簡単です。

segmentedImage = segmentImageUnet_mex(input_data,[1024 1024]);

セグメンテーションの有効な部分だけを抽出するには、セグメント化されたイメージにテスト データのマスク チャネルを乗算します。

segmentedImage = uint8(input_data(:,:,7)~=0) .* segmentedImage;

関数 medfilt2 を使用してノイズと散在ピクセルを取り除きます。

segmentedImage = medfilt2(segmentedImage,[5,5]);

U-Net でセグメント化された input_data の表示

次のコード行は、クラス名のベクトルを作成します。

classNames = net.Layers(end).Classes;

セグメント化された RGB テスト イメージにラベルを重ね合わせ、このセグメンテーション イメージにカラー バーを追加します。

% Display input data

figure(1);
imshow(histeq(input_data(:,:,1:3)));
title('Input Image');
cmap = jet(numel(classNames));
segmentedImageOut = labeloverlay(imadjust(input_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),segmentedImage,'Transparency',0,'Colormap',cmap);

% Display segmented data

figure(2);
imshow(segmentedImageOut);
title('Segmented Image Output');
N = numel(classNames);
ticks = 1/(N*2):1/N:1;
colorbar('TickLabels',cellstr(classNames),'Ticks',ticks,'TickLength',0,'TickLabelInterpreter','none');
colormap(cmap)
title('Segmented Image using Mkldnn');
segmentedImageOverlay = labeloverlay(imadjust(input_data(:,:,4:6),[0 0.6],[0.1 0.9],0.55),segmentedImage,'Transparency',0.7,'Colormap',cmap);
figure(3);
imshow(segmentedImageOverlay);
title('Segmented Overlay Image');

参考文献

[1] Ronneberger, Olaf, Philipp Fischer, and Thomas Brox. "U-Net: Convolutional Networks for Biomedical Image Segmentation." arXiv preprint arXiv:1505.04597, 2015.

[2] Kemker, R., C. Salvaggio, and C. Kanan. "High-Resolution Multispectral Dataset for Semantic Segmentation." CoRR, abs/1703.01918, 2017.

参考

| | (Deep Learning Toolbox)

関連するトピック