このページの内容は最新ではありません。最新版の英語を参照するには、ここをクリックします。
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 を選択します。
肺のセグメント化
動的輪郭手法を使用して 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_XY
と mask_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");
x、y、z の各次元に、元のファイル メタデータから収集したボクセルの間隔を指定します。メタデータは、アドオン エクスプローラーからダウンロードしたイメージ データには含まれていません。
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