# Node.js 中 DICOM 影像處理的實務取捨與方案選擇 在開發 PACS(Picture Archiving and Communication System)的過程中, 「如何在 Node.js 環境下正確且穩定地處理 DICOM 影像」一直是一個極具挑戰性的問題 這篇文章記錄了筆者從專案初期開始,一路嘗試不同技術組合、踩過實務上的坑, 最終選擇解決方案的完整思考歷程 ## 第一階段:DCMTK + Python 的混合方案 最早期的做法,是以 **DCMTK** 作為核心的 DICOM 工具鏈 [DCMTK](https://github.com/DCMTK/dcmtk) 是以 C++ 撰寫、歷史悠久且功能完整的 DICOM 函式庫 在實作上,筆者透過命令列方式呼叫 `dcmj2pnm`,將 DICOM 影像轉換為 PNG、JPEG 等常見格式 ### 遇到的問題 第一個明顯限制是: - `dcmj2pnm` **不支援 JPEG2000 編碼的 DICOM 影像解碼** 為了處理 JPEG2000,我只好再引入 **Python**,使用 **pydicom** 套件進行轉換 然而,問題並不只在於格式支援,而是在於**影像正確性**: - 必須自行處理 windowing 計算 (Window Center、Window Width、Rescale Intercept、Rescale Slope) - 一旦計算錯誤,輸出的影像亮度與對比就會完全失真 ### 架構上的代價 這個階段的架構問題非常明顯: - 同時依賴 **DCMTK(C++)** 與 **Python** - Node.js 需要透過 child process 與外部程式互動 - 為了解決單一功能,引入並維護一個 Python 微服務 **結果是:功能可行,但整體架構破碎、維運成本高。** ## 第二階段:dcmjs 與 Node.js 原生解法的嘗試 [dcmjs](https://github.com/dcmjs-org/dcmjs) 可以說是近年來 nodejs 在 DICOM 處理上最偉大的進步 ### 記憶體瓶頸 (致命問題) 不過筆者在深入看讀取 DICOM 檔案的程式碼發現, ```javascript static readFile( buffer, options = { ignoreErrors: false, untilTag: null, includeUntilTagValue: false, noCopy: false, forceStoreRaw: false } ) { // .... } ``` `readFile(buffer)`這個函數,它所接受的是 buffer,也就是說如果有一個 40MB 的 DICOM 檔案,你就會占用 40MB 的記憶體,這在併發處理 DICOM 影像時,非常有高機率出現 OOM 的問題 為了這個問題,筆者有透過 AI 協作做出了一個串流版本[dcmjs-stream](https://github.com/Chinlinlee/dcmjs-stream) ### 另一個限制 (Transcode) 在 PACS 應用上還有一個 transcode 的功能 (例如:將 Raw Image 的 DICOM 轉成 JPEG Image 的 DICOM),這個功能只能使用[dcmjs-codecs](https://github.com/PantelisGeorgiadis/dcmjs-codecs)來實作,就一樣會面臨 OOM 的問題 ## 最終選擇:DCM4CHEE + Java Bridge 這是筆者最後選擇的方案,因為它可以支援 DICOM 轉 JSON、各種 DICOM 的轉圖、Transcode 可以說是非常地全面,但你可能會想到,我們用的不是 node.js 嗎?這 java 的套件是要怎麼用?這時候就可以透過黑科技 [java-bridge](https://www.npmjs.com/package/java-bridge),讓你可以在 Node.js 內去 call java 的函式 筆者也基於這個架構,實作了: - [dcm777](https://github.com/Chinlinlee/dcm777) - 部分沒辦法直接在 Node.js 搭配 Java-Bridge 執行的函式抽離到 Java 去處理 - [raccoon-dcm4che-bridge](https://github.com/Chinlinlee/raccoon-dcm4che-bridge) - 將 dcm4che 包裝為可在 Node.js 中使用的函式庫 ## 方案比較表 | 方案 | 優點 | 主要問題 | | :--- | :--- | :---| | DCMTK+Python | 穩定、工具成熟 | 架構破碎、需自行處理 windowing、多語言維運成本高 | | dcmjs | 純 Node.js、生態整合佳 | 高機率遇到記憶體占用高、容易 OOM | | DCM4CHEE + Java Bridge | 功能完整、效能穩定、臨床驗證充分 | 引入 JVM、部署複雜度提高 |
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up