ImagePy 是一款基於 Python 的可擴展圖像處理框架,可謂是 Python 版的 ImageJ,但設計更為精簡,可以輕鬆接入 scipy, scikit-image, opencv 等任何基於 numpy 的圖像處理庫。
Github地址:ImagePy 主頁:http://www.imagepy.org/
這裡展示幾個三維視圖,但是需要提醒讀者,三維可視化不等於三維分析,可視化有助於理解,並且可以直觀驗證算法效果,但初學者不要沉迷與三維特效,應注重分析問題的思路,數據處理技巧,把可視化當作一個輔助工具,而不是結果。
DEM數據進行地表重建
幾何圖形的三維渲染
以下是一個腦部MRI數據,讀者可以在這裡下載。我們今天要對影像序列中的willis環腦血管進行提取,測量其長度,體積,表面積,以及拓撲結構。
<腦部MRI 數據下載>
導入圖像:
File > Import > Import Sequence 導入圖像序列
Image > Type > Trans To Stack 轉換成連續棧(這是進行三維分析的前提)
分割
我們的問題難點依舊是分割,即在影像中分離我們關心的目標。說到分割,很多人反映的是閾值分割,的確在我們的影像中,血管由於注射了造影劑,比周圍亮,因而閾值分割是一個可以嘗試的方法。
我們用210作為閾值進行分割,然後做三維表面重建
我們發現重建之後,空間中存在大量的噪聲,其原因是顱骨的反射率也非常高,很難與血管從亮度上分離,並且一些比較細的血管出現了斷裂。
三維分水嶺法
我們嘗試另一種方法,分析問題:
閾值分割是一個非此即彼的判斷,因而在目標與非目標之間,如果存在亮度重疊,那麼勢必無法完美分割。而另一種方式是,我們採用兩個閾值,把像素分為三類,背景,待確定,前景。而待確定的部分由分水嶺算法完成。換言之前景,背景自由生長,最終在梯度最大的地方終止,就得到了邊界。
在此之前我們先對圖像做一個三維平滑,以及一個garmma矯正。三維平滑用最小的半徑,否則細血管會被淹沒,garmma是對亮度做一個指數形式非線性映射,類似ps裡面的曲線調整,這樣可以保留亮部,抑制暗部。(但是對閾值分割依舊沒有幫助,因為garmma函數不能改變亮度次序,主要目的是降低其他部位與黑色背景的差異,為分水嶺提供便利)
Kit3D > Filter 3D > Gaussian 3D sigma:0.7
Process > Math > Garmma value:3
Kit3D > Filter 3D > Up Down Watershed 3D Low:34 High:117
其原理如下,標記了紅色和綠色區域後,對原始三維圖像做梯度,即凸顯變化部分,然後紅色和綠色區域在梯度圖上生長,最終在梯度最大的地方終止,感性的說,血管壁很亮,很難被穿過,最後內部是紅色,外部是綠色。
Kit3D > Viewer 3D > 3D Surface threshold:128 march step:1 down scale:1
觀察結果,我們甚至得到了良好的顱骨與部分腦組織,是的,我們依舊無法保證得到純淨的血管目標,但是我們的噪聲已經不那麼零碎了,後續有辦法去除他們。
分水嶺相比閾值的優勢:
1)結果碎片不像閾值那麼多,為後續處理提供了很好的條件。
2)結果對與閾值設定不敏感(因為最終邊界是算法自動尋找梯度最大的位置,這也意味著結果更加客觀)
去除雜物首先我們觀察,大塊噪聲都在顱骨部位,空間上可以與目標簡單分離。
製作圓形選區,然後 Image > Clear Out,清除背景
再次三維重建 Kit3D > Viewer 3D > 3D Surface threshold:128 march step:1 down scale:1
注意,如果不是有意要疊加效果,請在三維重建之前關閉之前的三維窗口,否則結果會疊加。
我們看到目標已經比較純淨了,剩下的是少量懸浮碎片。
我們用聯通區域的幾何特徵進行過濾。
Kit3D > Analysis 3D > Geometry Analysis 3D 對區域中每塊連通區域進行位置,體積分析。
在結果中我們看到兩個大的聯通區域,體積是3685,11371,而其他的都遠小於這兩塊,因而執行幾何過濾器,去掉體積小於1000的,注意以上過程都使用8鄰域。
Kit3D > Analysis 3D > Geometry 3D Filter back color:0 去掉體積小於1000的塊
再次三維重建 Kit3D > Viewer 3D > 3D Surface threshold:128 march step:1 down scale:1
至此我們得到了理想的分割結果。這個掩模是重要的中間過程,如果有必要,可以用Image > Export > Export Sequence 進行輸出(二值圖想用png會得到無損理想的壓縮效果)
表面積,體積測量得到掩模後,我們可以對目標進行體積,表面積測量,所謂體積,本質上是累計像素個數,而表面積,其實需要三維表面重建算法,也就是得到用於渲染的表面三角形。
由於拓撲分析會對圖像做骨架處理,為了不破壞之前的掩模結果,我們用 Image > Duplicate 對圖像進行複製,命名為topograph。
拓撲構建
Kit3D > Network 3D > Skeleton 3D 三維圖像骨架化
Kit3D > Network 3D > Build Graph 3D 構建拓撲結構
拓撲可視化
接著我們可以對骨架進行可視化,Kit3D > Network 3D > Show Graph 3D
我們觀察在兩個分支上有太多的分叉,我們來修剪它(醫學上有分叉可能有其他意義,這裡只是展示如何去除分支)
把圖轉到一個分支較多的區域,我們看到,18-16之間的邊就是一段分支。
骨架修剪
Kit3D > Network 3D > Graph Statistic 3D 進行節點,邊統計,我們看到16-18之間的邊距離是11.42。並且瀏覽數據,有一部分在十以下的邊,我們選定15作為修剪閾值。
Kit3D > Network 3D > Graph Cut Branch 3D limit:15 對骨架進行修剪。
修剪過後,只是圖像內容發生了變化,但拓撲結構並沒有更新,需要重新執行如操作:
Kit3D > Network 3D > Skeleton 3D 三維圖像骨架化
Kit3D > Network 3D > Build Graph 3D 構建拓撲結構
Kit3D > Network 3D > Show Graph 3D 再次可視化
這次我們得到了純淨,理想的結果。接下來可以對拓撲結構進行統計分析了。
拓撲統計:
Kit3D > Network 3D > Graph Statistic 3D 得到了邊和節點信息
Kit3D > Network 3D > Graph Summarise 進行拓撲匯總,可以看到有兩個聯通部分
點擊掩模圖像,(有必要可以複製一份,命名為vessel)
此前我們重建的效果表面都是粗糙的,因為我們的區域是二值的,像素勢必會產生稜角,最後為了得到更好的視覺效果,我們對圖像進行一個高斯模糊,並且降低重建時使用的閾值,讓血管比實際粗一些。(這次我們為了得到疊加效果,請不要關閉之前的骨架三維圖,如果已經關閉,可以激活骨架圖,然後再次用 Show Graph 3D 進行生成)
Kit3D > Filters 3D > Gaussian 3D sigma:0.7 做一個小尺度三維平滑
Kit3D > Viewer 3D > 3D Surface threshold:100 march step:1 down scale:1 三維重建
得到疊加效果,半透明的血管內可以看到骨架結構,節點位置用紅色帶有ID標識的小球表示。
以上的實例中,覆蓋了大多三維操作,最後我們介紹一下三維工具,三維工具需要點擊最右側的下拉按鈕,選擇ToolKit3D。裡面多數是一些功能的快捷鍵。
以下從左到右,分別是:
Build Graph 3D, Cursor 3D, Graph Cut Brach 3D, Show Graph 3D, 3D Surface 的快捷按鈕,除了Cursor 3D,其他功能以上都有涉及,這裡簡單介紹Cursor 3D的功能。
我們的數據是二維序列,而重建後是三維表面,有時候,我們需要知道三維中的這個節點,對應二維圖像的那個位置,或者想知道二維圖像上這個白色區域,在三維空間中的什麼位置,而這個Cursor 3D工具,就可以起到聯通圖像與三維模型的作用。
雙擊Cursor 3D圖標,可以設置光標半徑及顏色,然後用滑鼠在圖像序列中點擊,移動,也可滑動滾輪在z方向移動,而對應的三維圖中會實時出現其對應的位置。
練習以上分析過程,覆蓋了很多分析技巧,並且數據分割的複雜度比較高,最後留一組胸腔MRI數據給讀者當作練習,數據可以在這裡下載。(提示,由於解析度較高,三維平滑的sigma可以選擇1)
<胸部MRI數據下載>
ImagePy是我個人用業餘時間維護開源項目,屬於公益事業,其發展與完善需要大家的支持,如果覺得ImagePy對你有幫助,請點擊star,以如下方式給予您的支持:
在此紀念,2019/07/26 739 star在 Github項目地址 右上角為項目點一顆star,以示支持。
把項目推薦給同學和朋友,把本文進行轉載。
本人也在擬寫一本通俗易懂的,理論,實驗相結合的圖像處理教程,屆時請大家捧場。
本文作者,閆霄龍_ImagePy,為閆大打Call!!!
QQ群:596310256 歡迎共同探討學習圖像處理問題。
文中連結,點擊"閱讀原文"即刻探索!