fo-dicom是一個基于C#開發的庫,用于處理DICOM(Digital Imaging and Communications in Medicine)格式的數據。DICOM是一種用于醫學影像和相關信息的標準格式,廣泛應用于醫學領域。fo-dicom提供了多平臺支持,可在 Windows、Linux 和 macOS 等操作系統上運行。
fo-dicom庫的設計理念是提供一個方便、易用、功能強大的工具,用于處理、讀取、寫入和修改DICOM文件。該庫提供了豐富的API,支持對DICOM文件的標簽進行讀取和設置,支持對DICOM文件的編碼和解碼,支持對DICOM文件的傳輸和存儲。
fo-dicom庫還提供了對DICOM消息流的封裝,使得開發者可以方便地實現自定義的DICOM服務。該庫還支持對網絡底層的封裝,使得開發者可以輕松地實現基于網絡的DICOM通信。
開源庫地址:https://github.com/fo-dicom/fo-dicom。
fo-dicom庫的產生是為了解決醫學圖像處理和DICOM數據交換的需求。在醫學領域,DICOM(Digital Imaging and Communications in Medicine)是一種用于存儲、傳輸和共享醫學影像和相關信息的標準。由于醫學影像數據的特殊性和復雜性,需要一個專門的庫來處理DICOM數據,并提供方便的接口和工具。
背景上來說,DICOM標準的出現是為了解決各種醫學設備之間的互操作性問題。在過去,不同廠商的醫學設備使用自己的私有格式來存儲和傳輸影像數據,這導致了數據共享和集成的困難。DICOM標準的制定使得不同設備可以使用統一的格式和通信協議,從而實現醫學影像的無縫交流和協作。
fo-dicom作為一個開源的DICOM庫,旨在提供一個易于使用且功能強大的工具,使得開發者能夠處理醫學圖像和相關數據。它基于DICOM標準,提供了讀取、創建、修改和存儲DICOM數據的功能,同時支持醫學圖像的加載、處理和保存。此外,fo-dicom還具備與遠程PACS(Picture Archiving and Communication System)或其他DICOM節點的網絡通信能力,以及查詢和檢索功能,方便用戶根據條件查詢和獲取DICOM實例。
閱讀官方文檔,即可獲得安裝方法:https://fo-dicom.github.io/stable/v5/index.html。
開箱即用的 fo-dicom 默認為內部類FellowOakDicom.Imaging.IImage 樣式的圖像渲染。若要切換到桌面樣式或 ImageSharp 樣式的圖像呈現,首先必須添加所需的 nuget 包,然后調用:
new DicomSetupBuilder() .RegisterServices(s => s.AddFellowOakDicom().AddImageManager<WinFormsImageManager>()).Build();
或:
new DicomSetupBuilder() .RegisterServices(s => s.AddFellowOakDicom().AddImageManager<ImageSharpImageManager>()).Build();
然后,在渲染時,可以通過以下方式將 IImage 強制轉換為類型。
var image = new DicomImage("filename.dcm");var bitmap = image.RenderImage().As<Bitmap>();
或:
var image = new DicomImage("filename.dcm");var sharpimage = image.RenderImage().AsSharpImage();
Fellow Oak DICOM 使用 ,因此如果您已經在使用它,則 Fellow Oak DICOM 日志記錄將自動顯示。
Microsoft.Extensions.Logging
過去,Fellow Oak DICOM 有一個用于日志記錄的自定義抽象:ILogger 和 ILogManager。 出于向后兼容性的目的,這仍然受支持,但不建議用于新應用程序。
services.AddLogManager<MyLogManager>();
其中 MyLogManager 如下所示:
using FellowOakDicom.Log;public class MyLogManager: ILogManager { public ILogger GetLogger(string name) { ... }}
這里有許多使用 fo-dicom 的簡單示例應用程序,它們位于單獨的存儲庫中。這些還包括示例 以前包含在 VS 解決方案的“示例”子文件夾中。
var file = DicomFile.Open(@"test.dcm"); // Alt 1var file = await DicomFile.OpenAsync(@"test.dcm"); // Alt 2var patientid = file.Dataset.GetString(DicomTag.PatientID);file.Dataset.AddOrUpdate(DicomTag.PatientName, "DOE^JOHN");// creates a new instance of DicomFilevar newFile = file.Clone(DicomTransferSyntax.JPEGProcess14SV1);file.Save(@"output.dcm"); // Alt 1await file.SaveAsync(@"output.dcm"); // Alt 2
var image = new DicomImage(@"test.dcm");image.RenderImage().AsBitmap().Save(@"test.jpg"); // Windows Forms
var client = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU", "ANY-SCP");await client.AddRequestAsync(new DicomCStoreRequest(@"test.dcm"));await client.SendAsync();
var server = new DicomServer<DicomCEchoProvider>(12345);var client = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU", "ANY-SCP");client.NegotiateAsyncOps();// Optionally negotiate user identityclient.NegotiateUserIdentity(new DicomUserIdentityNegotiation{ UserIdentityType = DicomUserIdentityType.Jwt, PositiveResponseRequested = true, PrimaryField = "JWT_TOKEN"});for (int i = 0; i < 10; i++) await client.AddRequestAsync(new DicomCEchoRequest());await client.SendAsync();
var cfind = DicomCFindRequest.CreateStudyQuery(patientId: "12345");cfind.OnResponseReceived = (DicomCFindRequest rq, DicomCFindResponse rp) => { Console.WriteLine("Study UID: {0}", rp.Dataset.GetString(DicomTag.StudyInstanceUID));};var client = DicomClientFactory.Create("127.0.0.1", 11112, false, "SCU-AE", "SCP-AE");await client.AddRequestAsync(cfind);await client.SendAsync();
var cmove = new DicomCMoveRequest("DEST-AE", studyInstanceUid);var client = DicomClientFactory.Create("127.0.0.1", 11112, false, "SCU-AE", "SCP-AE");await client.AddRequestAsync(cmove);await client.SendAsync();
// It is better to increase 'associationLingerTimeoutInMs' default is 50 ms, which may not be// be sufficientvar dicomClient = DicomClientFactory.Create("127.0.0.1", 12345, false, "SCU-AE", "SCP-AE",DicomClientDefaults.DefaultAssociationRequestTimeoutInMs, DicomClientDefaults.DefaultAssociationReleaseTimeoutInMs,5000);var txnUid = DicomUIDGenerator.GenerateDerivedFromUUID().UID;var nActionDicomDataSet = new DicomDataset{ { DicomTag.TransactionUID, txnUid }};var dicomRefSopSequence = new DicomSequence(DicomTag.ReferencedSOPSequence);var seqItem = new DicomDataset(){ { DicomTag.ReferencedSOPClassUID, "1.2.840.10008.5.1.4.1.1.1" }, { DicomTag.ReferencedSOPInstanceUID, "1.3.46.670589.30.2273540226.4.54" }};dicomRefSopSequence.Items.Add(seqItem);nActionDicomDataSet.Add(dicomRefSopSequence);var nActionRequest = new DicomNActionRequest(DicomUID.StorageCommitmentPushModelSOPClass, DicomUID.StorageCommitmentPushModelSOPInstance, 1){ Dataset = nActionDicomDataSet, OnResponseReceived = (DicomNActionRequest request, DicomNActionResponse response) => { Console.WriteLine("NActionResponseHandler, response status:{0}", response.Status); },};await dicomClient.AddRequestAsync(nActionRequest);dicomClient.OnNEventReportRequest = OnNEventReportRequest;await dicomClient.SendAsync();private static Task<DicomNEventReportResponse> OnNEventReportRequest(DicomNEventReportRequest request){ var refSopSequence = request.Dataset.GetSequence(DicomTag.ReferencedSOPSequence); foreach(var item in refSopSequence.Items) { Console.WriteLine("SOP Class UID: {0}", item.GetString(DicomTag.ReferencedSOPClassUID)); Console.WriteLine("SOP Instance UID: {0}", item.GetString(DicomTag.ReferencedSOPInstanceUID)); } return Task.FromResult(new DicomNEventReportResponse(request, DicomStatus.Success));}
具有高級 DICOM 客戶端連接的 C-ECHO:手動控制 TCP 連接和 DICOM 關聯。
var cancellationToken = CancellationToken.None;// Alternatively, inject IDicomServerFactory via dependency injection instead of using this static methodusing var server = DicomServerFactory.Create<DicomCEchoProvider>(12345); var connectionRequest = new AdvancedDicomClientConnectionRequest{ NetworkStreamCreationOptions = new NetworkStreamCreationOptions { Host = "127.0.0.1", Port = server.Port, }};// Alternatively, inject IAdvancedDicomClientConnectionFactory via dependency injection instead of using this static methodusing var connection = await AdvancedDicomClientConnectionFactory.OpenConnectionAsync(connectionRequest, cancellationToken);var associationRequest = new AdvancedDicomClientAssociationRequest{ CallingAE = "EchoSCU", CalledAE = "EchoSCP", // Optionally negotiate user identity UserIdentityNegotiation = new DicomUserIdentityNegotiation { UserIdentityType = DicomUserIdentityType.UsernameAndPasscode, PositiveResponseRequested = true, PrimaryField = "USERNAME", SecondaryField = "PASSCODE", }};var cEchoRequest = new DicomCEchoRequest();using var association = await connection.OpenAssociationAsync(associationRequest, cancellationToken);try{ DicomCEchoResponse cEchoResponse = await association.SendCEchoRequestAsync(cEchoRequest, cancellationToken).ConfigureAwait(false); Console.WriteLine(cEchoResponse.Status);}finally{ await association.ReleaseAsync(cancellationToken);}
fo-dicom 有一個活躍的社區,包括眾多貢獻者和維護者。它在 GitHub 上有一個開放的倉庫,用戶可以在其中提交問題、提出建議和貢獻代碼。fo-dicom 的更新頻率較高,并得到了廣泛的應用和認可。
為了方便新手學習官方構建了樣例庫:https://github.com/fo-dicom/fo-dicom-samples。
同時支持多個平臺的案例開發開發:
fo-dicom 的未來計劃包括進一步增強圖像處理功能、優化性能、改進網絡通信和增加對新版 DICOM 標準的支持。通過不斷改進和擴展功能,fo-dicom 將繼續滿足用戶對醫學圖像處理和數據交互的需求。
今天先介紹到這里,后續我將持續分享關于fo-dicom庫的使用經驗技巧,歡迎有需要的朋友持續關注。
本文鏈接:http://www.www897cc.com/showinfo-26-87004-0.htmlFo-dicom,第一個基于.NET Standard 2.0 開發的DICOM開源庫
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。郵件:2376512515@qq.com