在剛結束的這個夏天裡,我是 NASA 格倫中心 GVIS 實驗室的實習生,我將我對開源的熱情帶到了那裡。我的任務是改進我們實驗室對 Dan Schroeder 開發的一個開源流體動力學模擬器的貢獻。原本的模擬器可以顯示用戶用鼠標繪制的障礙物,並建立計算流體動力學模型。我們團隊的貢獻是加入圖像處理的代碼,分析實況視頻的每一幀以顯示特定的物體如何與液體相互作用。而且,我們還要做更多事情。
我們想要讓圖像處理部分更加健壯,所以我致力於改善圖像處理庫。
得益於新的庫,模擬器可以檢測輪廓、進行空間坐標變換以及找到物體的質心。圖像處理並不直接與流體動力學模擬器物理相關。它用攝像頭檢測物體,並且獲取物體輪廓,為流體模擬器創建一個障礙物。隨後,流體模擬器開始運行,而輸出結果會被投射到真實物體上。
我的目標是通過以下三個方面改進模擬器:
找尋物體的輪廓
找尋物體的質心
能對物體中心進行相關的精確轉換
我的導師建議我安裝 Node.js 、 OpenCV 和 Node.js bindings for OpenCV。在等待軟件安裝的過程中,我查看了 OpenCV 的 GitHub 主頁上的示例源碼。我發現示例源碼使用 JavaScript 寫的,而我還不懂 JavaScript ,所以我在 Codecademy 上學了一些課程。兩天後,我對 JavaScript 依舊生疏,不過我還是開始了我的項目……它包含了更多的 JavaScript 。
檢測輪廓的示例代碼工作得很好。事實上,它使得我用幾個小時就完成了第一個目標!獲取一幅圖片的輪廓,它看起來像這樣:
包括所有輪廓的原始圖
檢測輪廓的示例代碼工作得有點好過頭了。不僅物體的輪廓被檢測到了,整個圖片中的輪廓都檢測到了。這會導致模擬器要與那些沒用的輪廓打交道。這是一個嚴重的問題,因為它會返回錯誤的數據。為了避免模擬器接觸到不想要的輪廓,我加了一個區域約束。輪廓要位於一定的區域范圍內才會被畫出來。區域約束使得輪廓變干淨了。
過濾後的輪廓,包含了陰影輪廓
雖然無關的輪廓沒有了,但是圖像還有個問題。圖像本該只有一個輪廓,但是它來回繞了自己兩次,沒有完整地圈起來。區域在這裡不能作為決定因素,所以必須試試其他方式。
這一次,我不是直接去找尋輪廓,而是先將圖片轉換成二值圖。二值圖是轉換之後只有黑白像素的圖片。為了獲取到二值圖我先把彩色圖轉成灰度圖。轉換之後我再用阈值函數對圖片進行處理。阈值函數遍歷圖片每個像素點的值,如果值小於 30 ,像素的顏色就會改成黑色。否則取反。在原始圖片轉換成二值圖之後,結果變成這樣:
二值圖
然後我獲取了二值圖的輪廓,結果是一個更干淨的輪廓,沒有了陰影輪廓。
最後的干淨輪廓
這個時候,我可以獲取干淨的輪廓、計算質心了。可惜的是,我沒有足夠的時間去完成質心的相關變換。由於我的實習時間只剩下幾天了,我開始考慮我在這段有限時間內能做的其它事情。其中一個就是邊界矩形。邊界矩形是包含了圖片輪廓的最小四邊形。邊界矩形很重要,因為它是在頁面上縮放輪廓的關鍵。雖然很遺憾我沒時間利用邊界矩形做更多事情,但是我仍然想學習它,因為它是個很有用的工具。
最後,經過以上的努力,我完成了對圖像的處理!
最終圖像,紅色的邊界矩形和質心
當這些圖像處理代碼寫完之後,我用我的代碼替代了模擬器中的老代碼。令我意外的是,它可以工作。
嗯,基本可以。
程序有內存洩露,每 1/10 秒洩露 100MB 。我很高興不是因為我的代碼。壞消息是我並不能修復它。另一個好消息是仍然有解決方法,雖然並非最理想的,但我可以使用。這個方法是不斷檢查模擬器使用的內存,當使用內存超過 1GB 時,重新啟動模擬器。
在 NASA 實驗室,我們會使用很多的開源軟件,沒有這些開源軟件的幫助,我不可能完成這些工作。
作者:Lauren Egts 譯者:willowyoung 校對:PurlingNayuki