Main Content

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

3 次元胸部スキャンからの肺のセグメント化

この例では、動的輪郭 (snakes) を使用して 3 次元セグメンテーションを実行し、"ボリューム ビューアー" アプリを使用して結果を表示する方法を説明します。

データの準備

人体胸部 CT スキャン データをワークスペースに読み込みます。この例を実行するには、アドオン エクスプローラーを使用して MathWorks™ からサンプル データをダウンロードしなければなりません。アドオン エクスプローラーを使用したサンプル データのインストールを参照してください。

load chestVolume
whos
  Name        Size                     Bytes  Class    Attributes

  V         512x512x318            166723584  int16              

CT スキャン データを int16 から single に変換して [0, 1] の範囲に値を正規化します。

V = im2single(V);

"ボリューム ビューアー" アプリを使用して胸部スキャンを表示します。

volumeViewer(V)

"ボリューム ビューアー" には、特定のタイプのデータの最適なビューを提供することを目的とした alphamap が事前に設定されています。胸部スキャンの最適な表示を可能にするには、事前に設定された CT-Bone を選択します。

SegmentLungsFrom3DChestScanExample_01.png

肺のセグメント化

動的輪郭手法を使用して CT スキャン データ内の肺をセグメント化します。動的輪郭は初期シード ポイントを必要とする領域拡張アルゴリズムです。例では、イメージの領域分割アプリを使用し、直交する 2 個の 2 次元スライス (XY 平面と XZ 平面に 1 個ずつ) をセグメント化することによって、このシード マスクを作成します。次にこの例では、これら 2 つのセグメンテーションを 3 次元マスクに挿入します。この例では、このマスクを関数activecontourに渡して、胸腔内の肺の 3 次元セグメンテーションを作成します。(この例では動的輪郭メソッドを使用しますが、塗りつぶしのような他のセグメンテーション手法を使用しても同じ目的を実現できます)。

XY 次元と XZ 次元の両方の中心スライスを抽出します。

XY = V(:,:,160);
XZ = squeeze(V(256,:,:));

関数 imshow を使用して 2 次元スライスを表示します。

figure
imshow(XY,[],"Border","tight")
imshow(XZ,[],"Border","tight")

"イメージの領域分割" アプリでセグメンテーションを実行できます。2 次元スライスを入力引数として指定し、imageSegmenter コマンドを使用してアプリを開きます。

imageSegmenter(XY)

セグメンテーション プロセスを開始するには、[しきい値] タブで [しきい値] をクリックして肺のスライスを開きます。[しきい値] タブで、[手動しきい値] オプションを選択し、しきい値スライダーを動かして肺の良好なセグメンテーションが得られるしきい値を指定します。[マスクの作成] をクリックしてしきい値処理を確定し、[セグメンテーション] タブに戻ります。

アプリは次のコードを実行してイメージのしきい値処理を行います。

BW = XY > 0.5098;

この肺の初期セグメンテーションの後に、[マスクの調整] メニューのオプションを使用してマスクをクリーンアップします。

アプリで各オプションをクリックして、肺が前景になるようにマスク イメージを反転させ ([マスクの反転])、肺以外のセグメント化された要素を削除し ([境界のクリア])、肺のセグメンテーション内の穴を塗りつぶす ([穴の塗りつぶし]) ことができます。最後に、[モルフォロジー] オプションを使用して肺のセグメンテーションのエッジを滑らかにします。[モルフォロジー] タブで、[マスクの収縮] 操作を選択します。これらの手順を実行した後に、[バイナリの表示] を選択して、マスク イメージをワークスペースに保存します。

アプリは次のコードを実行してマスクを調整します。

BW = imcomplement(BW);
BW = imclearborder(BW);
BW = imfill(BW, "holes");
radius = 3;
decomposition = 0;
se = strel("disk",radius,decomposition);
BW = imerode(BW, se);
maskedImageXY = XY;
maskedImageXY(~BW) = 0;
imshow(maskedImageXY)

XZ スライスに対して同じ操作を実行します。[イメージの読み込み] を使用して、変数 XZ を選択します。しきい値処理を使用して、肺の初期セグメンテーションを実行します。XZ スライスに対して [グローバルしきい値] オプションを使用すると、適切なセグメンテーションが作成されます (以下のコードでの imbinarize の呼び出し)。XY スライスの場合と同様に、[マスクの調整] メニューのオプションを使用して、滑らかな肺のセグメンテーションを作成します。[モルフォロジー] タブでの収縮操作で、半径 13 を指定して小さい余分なオブジェクトを削除します。

XZ スライスをセグメント化し、結果を滑らかにするために、アプリは次のコードを実行します。

BW = imbinarize(XZ);
BW = imcomplement(BW);
BW = imclearborder(BW);
BW = imfill(BW,"holes");
radius = 13;
decomposition = 0;
se = strel("disk",radius,decomposition);
BW = imerode(BW, se);
maskedImageXZ = XZ;
maskedImageXZ(~BW) = 0;
imshow(maskedImageXZ)

activecontour を使用したシード マスクの作成と肺のセグメント化

関数 activecontour に使用して肺をセグメント化する 3 次元シード マスクを作成します。

入力ボリュームと同じサイズの 3 次元 logical ボリュームを作成し、mask_XYmask_XZ を適切な空間位置に挿入します。

mask = false(size(V));
mask(:,:,160) = maskedImageXY;
mask(256,:,:) = mask(256,:,:)|reshape(maskedImageXZ,[1,512,318]);

この 3 次元シード マスクを使用して、動的輪郭メソッドで 3 次元ボリューム内の肺をセグメント化します。この操作には数分かかることがあります。質の高いセグメンテーションを取得するには、histeq を使用してボクセル値を利用可能な範囲に広げます。

V = histeq(V);

BW = activecontour(V,mask,100,"Chan-Vese");

segmentedImage = V.*single(BW);

セグメント化された肺を "ボリューム ビューアー" アプリで表示します。

volumeViewer(segmentedImage)

レンダリング エディターの alphamap 設定を操作して、肺のみが鮮明に表示されるようにできます。

セグメント化された肺の体積の計算

関数regionprops3を "volume" オプション付きで使用して肺のボリュームを計算します。

volLungsPixels = regionprops3(logical(BW),"volume");

xyz の各次元に、元のファイル メタデータから収集したボクセルの間隔を指定します。メタデータは、アドオン エクスプローラーからダウンロードしたイメージ データには含まれていません。

spacingx = 0.76;
spacingy = 0.76;
spacingz = 1.26*1e-6;
unitvol = spacingx*spacingy*spacingz;

volLungs1 = volLungsPixels.Volume(1)*unitvol;
volLungs2 = volLungsPixels.Volume(2)*unitvol;
volLungsLiters = volLungs1 + volLungs2
volLungsLiters = 5.7726

参考

| |