許自強(qiáng),王麗嘉
(上海理工大學(xué)健康科學(xué)與工程學(xué)院,上海 200093)
醫(yī)學(xué)成像技術(shù)已經(jīng)成為越來越重要的診斷手段。隨著數(shù)據(jù)量的爆炸式增長,人們對醫(yī)學(xué)圖像處理技術(shù)有了更高的要求。以醫(yī)學(xué)圖像分割為例,它是計算機(jī)輔助診斷的關(guān)鍵步驟,也是整個處理任務(wù)耗時較多的一步,現(xiàn)有的分割模型精度并不能滿足所有的應(yīng)用場景[1]。如何讓這些不夠精確但能夠起到一定輔助作用的模型盡快投入使用呢?在醫(yī)學(xué)圖像領(lǐng)域,已經(jīng)出現(xiàn)了一些符合醫(yī)學(xué)數(shù)字成像和傳輸協(xié)議(Digital Imaging and Communications in Medicine,DICOM)標(biāo)準(zhǔn)的優(yōu)秀開源軟件,如Sébastien Jodogne等開發(fā)的圖像歸檔與傳輸系統(tǒng)[2-3](Picture Archiving and Communication System,PACS)Orthanc[4],Open Health Imaging Foundation(OHIF)開發(fā)的OHIF Viewer[5]等,這些都為解決該問題提供了技術(shù)支持。文中提出一種對非全自動化流程可特別支持的,基于Web 的醫(yī)學(xué)圖像處理系統(tǒng)。
醫(yī)學(xué)圖像處理系統(tǒng)的主要數(shù)據(jù)對象是DICOM文件,系統(tǒng)除了提供圖像歸檔、圖像查看、數(shù)據(jù)在線訪問這些基礎(chǔ)功能之外,還應(yīng)提供一種表示圖像處理任務(wù)的方法,以便在各子系統(tǒng)之間傳遞處理任務(wù)的信息??紤]到一個完整的圖像處理任務(wù)可能涉及到人工介入,例如對圖像分割質(zhì)量進(jìn)行人工確認(rèn)和對手術(shù)方案進(jìn)行規(guī)劃,系統(tǒng)還需要提供相應(yīng)的應(yīng)用編程接口(Application Programming Interface,API)。通常開發(fā)這樣的系統(tǒng)至少需要配備軟件工程師和算法工程師這兩類崗位的人員,軟件工程師擅長軟件開發(fā),熟悉整個系統(tǒng)的運(yùn)行機(jī)制,能夠快速定位系統(tǒng)故障;算法工程師專注于圖像處理模塊,通常對該模塊以外的部分不如軟件工程師熟悉。為了設(shè)計出易于開發(fā)、擴(kuò)展和維護(hù)的系統(tǒng),需要充分考慮各崗位人員的技術(shù)特點(diǎn)。基于上述分析,該系統(tǒng)的功能結(jié)構(gòu)圖如圖1 所示。
圖1 系統(tǒng)功能結(jié)構(gòu)圖
各模塊具體功能如下:
1)基礎(chǔ)功能模塊,該模塊提供用戶登錄驗證、用戶基本信息管理、用戶角色管理和數(shù)據(jù)分組管理等基礎(chǔ)功能。
2)圖像歸檔模塊,該模塊提供DICOM 文件的存儲、檢索和在線訪問功能,為了易與Web 系統(tǒng)和一些現(xiàn)成的工具包集成,該模塊需要支持DICOM 標(biāo)準(zhǔn)定義的DICOM Standard for Web-based medical imaging(DICOMWeb)[6-7]接口。
3)圖像處理模塊,該模塊提供醫(yī)學(xué)圖像處理功能,由于算法的實現(xiàn)往往依賴復(fù)雜的軟件環(huán)境,且不同算法可能依賴不同版本的軟件,大部分軟件不支持同時安裝多個版本,所以該模塊需要支持不同類別的算法使用獨(dú)立的運(yùn)行環(huán)境。
4)人機(jī)交互模塊,該模塊提供易于用戶使用的可視化操作界面,方便用戶進(jìn)行如用戶登錄、圖像查看、圖像分割和處理任務(wù)提交等操作。
5)任務(wù)管理模塊:一個處理任務(wù)至少包含一個步驟,文中也將處理任務(wù)的步驟稱為“計算作業(yè)”。該模塊用于創(chuàng)建、查詢和控制用戶提交的處理任務(wù)和維護(hù)計算作業(yè)的執(zhí)行情況。
6)作業(yè)調(diào)度模塊:該模塊用于異步和同步執(zhí)行計算作業(yè);支持按照各個節(jié)點(diǎn)的負(fù)載情況和作業(yè)優(yōu)先級分配作業(yè);支持啟動、查詢、中斷和結(jié)束計算作業(yè)的運(yùn)行;支持對計算節(jié)點(diǎn)的管理。考慮到高并發(fā)情況,還應(yīng)支持對計算節(jié)點(diǎn)進(jìn)行橫向擴(kuò)展。
7)文件管理模塊:該模塊提供文件的在線存取和管理的功能,通常醫(yī)學(xué)圖像處理的結(jié)果以文件的形式進(jìn)行表示,對外暴露的結(jié)果文件使用該模塊進(jìn)行管理。
在實際的醫(yī)學(xué)圖像處理任務(wù)中,總是會涉及到人工介入的操作。文中以肝臟手術(shù)規(guī)劃中的圖像分割任務(wù)為例,肝臟手術(shù)規(guī)劃需要精確分割大部分腹部臟器和肝內(nèi)管道系統(tǒng)。特別地對于肝內(nèi)管道系統(tǒng)這類小目標(biāo)來說,目前開發(fā)的全自動分割模型精度常常無法滿足實際要求。但是這些分割任務(wù)完全依靠人工操作,又非常繁瑣和耗時。在這樣的背景下,文中將這樣的圖像分割任務(wù)分解為“自動分割”和“手動分割”兩部分,“自動分割”表示使用計算機(jī)程序?qū)D像進(jìn)行初步分割,“手動分割”表示人工對自動分割的結(jié)果進(jìn)行二次確認(rèn),如果分割結(jié)果有錯誤或者缺少,則人工手動對其進(jìn)行修正,分割流程如圖2 所示。對于任何需要人工介入的操作,都可以使用類似的流程。
圖2 有人工介入的圖像分割流程
根據(jù)功能設(shè)計的邏輯結(jié)構(gòu),將系統(tǒng)劃分為前端App、API 網(wǎng)關(guān)、Web 后端、PACS、算法后端和調(diào)度中心共計六個子系統(tǒng),系統(tǒng)架構(gòu)圖如圖3 所示。
圖3 系統(tǒng)架構(gòu)圖
對各子系統(tǒng)的說明如下:
1)前端App:實現(xiàn)系統(tǒng)的人機(jī)交互模塊,是基于該系統(tǒng)對外開放的API 開發(fā)的一組應(yīng)用。
2)API 網(wǎng)關(guān):是前端和后端通信的橋梁,用于統(tǒng)一管理對外暴露的API。
3)Web 后端:實現(xiàn)系統(tǒng)的基礎(chǔ)功能模塊、任務(wù)管理模塊和文件管理模塊。
4)PACS:實現(xiàn)系統(tǒng)的圖像歸檔模塊。
5)算法后端:實現(xiàn)系統(tǒng)的圖像處理模塊。
6)調(diào)度中心:實現(xiàn)系統(tǒng)的作業(yè)調(diào)度模塊。
這里的前端是廣義上的前端,它們通過使用超文本傳輸協(xié)議(Hyper Text Transfer Protocol,HTTP)的API 經(jīng)過網(wǎng)關(guān)與后端通信,既包含了基于瀏覽器開發(fā)的Web App,又包含了原生App和命令行App。該系統(tǒng)目前設(shè)計開發(fā)兩個Web App 和一個命令行App,為了保持界面邏輯的清晰,用兩個Web App 分別承擔(dān)DICOM 圖像相關(guān)交互和一些其他的圖形化交互,它們的代號分別為DICOM Viewer和DICOM Explorer。其中DICOM Viewer 使用TypeScript 語言基于OHIF Viewer 開發(fā),是專門用于處理DICOM 文件的應(yīng)用,支持DICOMWeb 接口,用于實現(xiàn)DICOM 圖像的查看和手動分割功能;DICOM Explorer 使用TypeScript 語言基于Vue3 和Element-Plus[8]開發(fā),實現(xiàn)用戶管理、數(shù)據(jù)集管理、DICOM 文件上傳、處理任務(wù)提交和數(shù)據(jù)預(yù)覽等常規(guī)的交互操作。命令行App 的代號為DICOM Uploader,使 用Python 語言開 發(fā),用于解 決DICOM Explorer 上傳大批量數(shù)據(jù)時容易出現(xiàn)的性能問題和實現(xiàn)一些在Web 瀏覽器中難以實現(xiàn)的功能。
該系統(tǒng)后端有多個子系統(tǒng),互相通信均使用HTTP 協(xié)議,系統(tǒng)將會定義大量HTTP API,一部分API 如作業(yè)調(diào)度接口,出于安全和性能方面的考慮,應(yīng)僅供后端內(nèi)部使用,不對外部開放。除此之外系統(tǒng)還需要路由配置、登錄狀態(tài)檢查等功能,該系統(tǒng)使用API 網(wǎng)關(guān)來實現(xiàn)。常用的方案有使用NGINX、OpenResty、Kong 和Apache APISIX[9]作為網(wǎng)關(guān),通過性能、易用性、插件支持情況和功能等方面的比較,最終選用APISIX。APISIX 是云原生架構(gòu)的開源API網(wǎng)關(guān),相較于傳統(tǒng)的API 網(wǎng)關(guān),它提供了動態(tài)路由、插件熱加載等諸多能力,可以為海量API 和微服務(wù)提供安全可靠的動態(tài)、高性能、可擴(kuò)展的管理平臺。
該子系統(tǒng)基于Kotlin[11]語言和Spring Boot框架[11-12]開發(fā),實現(xiàn)基礎(chǔ)功能模塊、任務(wù)管理模塊和文件管理模塊這三個模塊功能?;A(chǔ)功能模塊實現(xiàn)了用戶管理和認(rèn)證功能,并引入數(shù)據(jù)集概念,將DICOM 圖像分配到不同的數(shù)據(jù)集下,即實現(xiàn)了數(shù)據(jù)分組管理的功能。文件管理模塊實現(xiàn)為所有管理的文件夾和文件分配唯一id的功能,并提供增刪改查操作的API。
2.3.1 處理任務(wù)類型的表示
系統(tǒng)要能夠集成多種類型的處理任務(wù),需要對處理任務(wù)的類型進(jìn)行表示,因此設(shè)計了名為PipelineDescriptor 的數(shù)據(jù)結(jié)構(gòu),其具體結(jié)構(gòu)如圖4 所示。該數(shù)據(jù)結(jié)構(gòu)的屬性及其說明如表1 所示,序號為1-7、8-13、14-17 的分別 是PipelineDescriptor、StageDescriptor、ParameterDescriptor 結(jié)構(gòu)的說明。
表1 PipelineDescriptor屬性
圖4 表示處理任務(wù)類型的數(shù)據(jù)結(jié)構(gòu)
該系統(tǒng)集成“肝內(nèi)血管分割”和“肺結(jié)節(jié)良惡性分析”這兩種類型的處理任務(wù)作為示例?,F(xiàn)給出“肺結(jié)節(jié)良惡性分析”類型的JSON 格式表示,如下所示:
除了高精度圖像分割之外,目前進(jìn)行如手術(shù)規(guī)劃之類的復(fù)雜操作也難以實現(xiàn)完全自動化,均可以通過類似的方式來定義流程。
2.3.2 計算作業(yè)所需圖像序列的指定
醫(yī)學(xué)圖像的采集通常是多模態(tài)的,即每個檢查(Study)下會采集多個序列(Series)的圖像,以“肝內(nèi)血管分割”類型的處理任務(wù)為例,需要對肝靜脈、門靜脈和肝動脈進(jìn)行精確的分割,肝靜脈通常在靜脈期或者延遲期有清晰成像,肝動脈通常在動脈期有清晰成像,所以要完成各類血管的分割,需要在多個序列圖像上分別運(yùn)行相應(yīng)的分割模型。DICOM標(biāo)準(zhǔn)沒有規(guī)定如何表示此類期相信息,各影像機(jī)構(gòu)通常利用DICOM 文件的SeriesDescription 標(biāo)簽來記錄,由于各機(jī)構(gòu)都使用自己約定的表述方式或者在掃描時由技師隨意指定,這種寬松的做法導(dǎo)致在開發(fā)圖像序列選擇程序時可能出現(xiàn)找不到所需序列圖像的情況。所以在表示計算作業(yè)類型的數(shù)據(jù)結(jié)構(gòu)StageDescriptor 中,設(shè)計了parameters 屬性,用于表示該類計算作業(yè)需要的參數(shù),用戶可以通過這個參數(shù)來手動指定所需圖像序列。
2.3.3 處理任務(wù)與計算作業(yè)的存儲
在數(shù)據(jù)庫中創(chuàng)建一張名為task 的數(shù)據(jù)表,用于存儲處理任務(wù)和計算作業(yè)的執(zhí)行狀況,數(shù)據(jù)表的關(guān)鍵字段及其說明如表2 所示。
表2 task數(shù)據(jù)表的關(guān)鍵字段及說明
該子系統(tǒng)為所有處理任務(wù)及其計算作業(yè)都創(chuàng)建一條數(shù)據(jù)庫記錄,且非自動計算作業(yè)的狀態(tài)變化必須通過顯式調(diào)用API 來進(jìn)行,以此表示用戶手動結(jié)束非自動計算作業(yè)。
PACS 子系統(tǒng)直接選用現(xiàn)成軟件,為了便于后期對該子系統(tǒng)進(jìn)行替換,PACS 子系統(tǒng)與其他子系統(tǒng)通過DICOMWeb接口通信。經(jīng)比較,開源版本的Orthanc是一個合適的選擇,使用PostgreSQL 替換Orthanc 默認(rèn)的數(shù)據(jù)庫,Orthanc 的性能達(dá)到較優(yōu)的狀態(tài)[4]。
為了和其他軟硬件保持兼容性,該系統(tǒng)充分利用DICOM 標(biāo) 準(zhǔn),使用Modality 為SEG 的DICOM 文件存儲分割結(jié)果。并做如下約定,為每種分割類型指定一個id,每個分割實例使用一個DICOM 序列存儲,且該序列下僅包含一個實例文件(Instance),并用SeriesDescription 標(biāo)簽記錄分割類型id,使用ContentCreateDate 標(biāo)簽和ContentCreateTime 標(biāo)簽記錄該分割結(jié)果的創(chuàng)建時間。將這個文件導(dǎo)入Orthanc 后,可通過DICOMWeb 接口查詢使用。為了以示區(qū)分,模型預(yù)測的分割類型id 以model_為前綴,目前規(guī)定的分割類型id 及其說明如表3 所示。
算法后端子系統(tǒng)專注于數(shù)據(jù)處理工作,且圖像處理程序多用Python 和C/C++開發(fā)。由于Python 相對于C/C++,可以很容易地集成其他編程語言的代碼,也有成熟易用的異步框架,所以算法后端選擇了Python 語言和Celery 框架[13-14]作為主要技術(shù),并以RabbitMQ 作為broker 和backend。算法后端集成的處理作業(yè)均以函數(shù)的形式對外開放,一個函數(shù)即實現(xiàn)一個計算作業(yè)。根據(jù)不同依賴環(huán)境的計算作業(yè)必須在不同的組別、同一任務(wù)的計算作業(yè)必須在同一組別的原則對其分組。如將“肝內(nèi)血管分割”的兩個計算作業(yè)編入liver-worker 組,將“肺結(jié)節(jié)的良惡性分析”的計算作業(yè)編入lung-worker 組。上述的liver-worker 和lung-worker 將作 為Celery 框架的兩類worker 實例運(yùn)行,按照配置的優(yōu)先級,在獨(dú)立的軟件環(huán)境中對計算作業(yè)進(jìn)行處理。
使用Celery 的Flower[15]插件對Celery 進(jìn)行擴(kuò)展,F(xiàn)lower 是一個基于Web 的監(jiān)控和管理Celery 集群的開源工具,適合作為該系統(tǒng)的調(diào)度中心。Flower 支持HTTP 協(xié)議的API,可以方便地與Web 后端子系統(tǒng)進(jìn)行集成。
該系統(tǒng)通過HTTP API 與外界通信,應(yīng)當(dāng)進(jìn)行全面的測試以保證功能的完整性和系統(tǒng)的安全性,并為每個對外開放的API 編寫易理解的文檔,該系統(tǒng)選用Apifox 作為API 文檔管理工具和API 測試工具。
該系統(tǒng)所有的代碼均使用Git 進(jìn)行版本管理,為了加快開發(fā)效率和方便測試,使用Jenkins 進(jìn)行持續(xù)集成,每當(dāng)有代碼提交Jenkins 將自動將其構(gòu)建為Docker 鏡像[16]。由于各組件均構(gòu)建為Docker 鏡像,該系統(tǒng)既可以使用Docker Compose 部署到單機(jī),又可使用Kubernetes 部署到計算機(jī)集群,部署工作非常方便。
系統(tǒng)通過將處理任務(wù)分解為計算作業(yè)的方式,對各種自動化程度的圖像處理任務(wù)都進(jìn)行了支持,這可以加速科研成果到產(chǎn)業(yè)的轉(zhuǎn)化,具備高度的靈活性和通用性。在實際應(yīng)用中發(fā)現(xiàn),系統(tǒng)仍有不足之處,即使對Orthanc 的配置進(jìn)行了優(yōu)化,部分DICOMWeb 接口還是存在性能問題,這個問題可以嘗試使用多個Orthanc 實例負(fù)載均衡,或者使用高性能的商用PACS 軟件來改善。