delphi 是什麼? 跟直接用 .NET 開發差異是什麼?

 

 


 

 

Delphi 是什麼?
Delphi 是由 Embarcadero 開發的一套快速應用程式開發 (RAD, Rapid Application Development) 工具和程式設計語言,最早由 Borland 開發,後來經過數次轉手。它主要基於 Object Pascal 語言,強調可視化設計和快速生成桌面應用程式。Delphi 的特色包括:

  1. 跨平台支援:現代版本(如 Delphi 10.4 Sydney、Delphi 11 Alexandria)支援 Windows、macOS、iOS、Android 和 Linux 的原生應用程式開發。
  2. 可視化設計工具:具有直觀的拖放式介面設計器,可以快速建立 GUI 應用程式。
  3. 原生程式碼編譯:Delphi 編譯出來的是原生機器碼 (Native Code),效能較高且無需額外的虛擬機器或執行時環境。
  4. 資料庫整合強:內建對各種資料庫(如 MySQL、SQLite、Oracle、SQL Server)的支援,方便進行企業級應用開發。

Delphi 與 .NET 開發的差異:

  1. 程式語言

    • Delphi 使用 Object Pascal 語言,而 .NET 通常使用 C#VB.NET
    • Object Pascal 相對較老,但語法清晰、穩定,C# 則較現代化且擁有更多語言特性。
  2. 執行環境

    • Delphi 編譯的是 原生機器碼 (Native Code),不需要額外的執行時 (Runtime) 支援。
    • .NET 編譯的是 中間語言 (IL, Intermediate Language),需要 .NET Runtime 或 .NET Core(.NET 5/6/7)來執行。
  3. 跨平台支援

    • Delphi 可直接跨平台編譯成 Windows、macOS、iOS、Android 的原生應用。
    • .NET Core(.NET 5 之後)也支援跨平台,但 GUI 應用(如 WinForms、WPF)目前主要還是支援 Windows,跨平台 GUI 則需使用 MAUI(.NET Multi-platform App UI) 或其他第三方框架(如 Avalonia)。
  4. 開發工具

    • Delphi 使用 RAD Studio IDE,內建強大的可視化設計工具。
    • .NET 則主要使用 Visual Studio,也支援 Visual Studio Code,但後者多用於 Web 和後端開發。
  5. 應用場景與生態系統

    • Delphi 適合 快速構建桌面應用嵌入式系統跨平台移植
    • .NET 更適合 企業級後端服務Web 應用雲端服務,特別是在 Windows 環境下有更好的整合性。

適用情境:

  • 如果你需要 跨平台桌面應用,且追求 高效能 (Native Code),Delphi 是很好的選擇。
  • 如果你主要在 Windows 環境開發企業應用,或需要 Web 與後端服務,.NET 的生態系統更強大且資源更豐富。

你有考慮要開發什麼類型的應用程式嗎?或者有其他技術需求,可以一起討論看看適合用哪種工具!

 

 


 

 

Delphi 如果要用 vs code 開發是可以的嗎? 如何找尋網路上的套件庫? 麗如果想要讓 Delphi 可以支援讀取 dicom 格式影像該如何做?

 

 


 

 

 

1. Delphi 可以用 VS Code 開發嗎?

目前 Delphi 無法直接在 VS Code 中完整開發,但可以透過以下方式部分整合:

  • 程式碼編輯:你可以在 VS Code 中編輯 Object Pascal 程式碼,但無法進行編譯或除錯。建議安裝 Pascal 語法高亮套件 以獲得語法高亮和程式碼補完。
  • 編譯與除錯:仍需使用 RAD Studio IDEDelphi Command Line Compiler (dcc32/dcc64) 進行編譯和除錯。可以在 VS Code 中設置 TasksTerminal 呼叫命令列編譯工具。

⚠️ 雖然 VS Code 有良好的編輯體驗,但 Delphi 的 UI 設計器和 RAD 功能無法在 VS Code 中使用


2. 如何找尋 Delphi 的套件庫?

Delphi 的套件庫主要來源有:

  1. GetIt Package Manager

    • 內建於 RAD Studio 中,可直接從 IDE 安裝各種第三方元件和函式庫。
    • 可用於快速安裝 UI 元件、資料庫連接、圖像處理等各種套件。
  2. 第三方資源網站:

    • GitHub:搜尋關鍵字如 Delphi DICOMDelphi Image Processing
    • Awesome Delphi:整理了大量 Delphi 開源套件,涵蓋各種應用場景。
    • Torry's Delphi Pages:有許多 Delphi 專用的元件和資源。

3. Delphi 如何支援讀取 DICOM 格式影像?

要在 Delphi 中讀取 DICOM 格式影像,可以考慮以下方案:

  1. DCMTK (DICOM ToolKit)

    • 開源的 DICOM 工具包,功能完整,但原生是 C++ 編寫。
    • 可以透過 DLL 動態連結 的方式,在 Delphi 中調用 DCMTK 的功能。
    • GitHub 專案DCMTK
  2. DicomVCL

    • 專為 Delphi 開發的 DICOM 讀取套件,支援影像顯示、標籤解析。
    • 可以在 Torry's Delphi Pages 或 GitHub 上找到開源版本。
  3. 內建 GDI+ 或第三方圖像處理庫

    • 若只需要顯示影像,可以考慮將 DICOM 轉換為常見格式(如 JPEG、BMP)後再顯示。
    • 可以使用 ImageMagickGDI+ 進行轉換。

推薦方案:使用 DicomVCL

這是最直接且與 Delphi 相容性最好的方案。步驟如下:

  1. 安裝 DicomVCL:

    • 從 GitHub 或 Torry's Delphi Pages 下載 DicomVCL 元件。
    • RAD Studio 中安裝元件Component > Install Component,選擇 DicomVCL 的 .pas 檔案進行安裝。
  2. 讀取 DICOM 檔案:

 

uses DicomReader;

var
 DicomImg: TDicomImage;
begin
 DicomImg := TDicomImage.Create;
 try
 DicomImg.LoadFromFile('你的DICOM檔案路徑.dcm');
 Image1.Picture.Bitmap.Assign(DicomImg.Bitmap); // 將影像顯示在 TImage 控制項中
 finally
 DicomImg.Free;
 end;
end;
  1. 顯示影像與資訊:

    • TImage 控制項放置於 Form 上,並將 DICOM 影像載入後直接顯示。
    • 可額外讀取 DICOM 的 Metadata,如患者資訊、影像描述等。

補充說明:

  • 若需 進行 DICOM 圖像處理或 DICOM 通訊 (如 PACS),可以考慮商業套件如 LEADTOOLS Medical Imaging SDKMitchell DICOM,但費用較高。
  • 若考慮改用其他語言,也可以參考 .NET 的 fo-dicom 套件Python 的 pydicom,這兩者都有較活躍的社群和更新。

你目前是要開發 DICOM Viewer 還是要 進行 DICOM 資料處理或分析?或者有其他需求,也可以進一步討論!

 

 


Delphi 有再持續更新嗎? 版本目前到多少呢?

 

 

 


 

 

 

是的,Delphi 持續更新,目前最新版本是 Delphi 12.2 Athens,於 2024 年 9 月發布。

此版本引入了多項新功能和改進,包括:

  • 高 DPI 支援:全面支援最新的 4K 及更高解析度顯示器,提供更清晰的字體和圖示,並在整個 IDE(包括 VCL 和 FMX 表單)中實現高解析度支援。

  • 設計時 VCL 樣式支援:允許開發者在設計時即時查看樣式化的表單和控制項,提升 UI 原型設計效率。

  • 多螢幕和多視窗改進:支援在多個視窗中同時設計和編輯同一表單,包括將表單設計器拖曳到不同視窗,方便在多螢幕環境下開發。

  • 歡迎頁面更新:全新設計的歡迎頁面,使用 VCL 重建,提供原生外觀且易於自訂的介面。

此外,Delphi 12.2 Athens 也支援最新的 Android 14 版本,確保開發者能夠針對最新的行動平台進行開發。

值得注意的是,Delphi 的開發商 Embarcadero 定期推出更新,以滿足現代開發需求,並保持與最新技術的相容性。

 

Delphi 有辦法支援使用 python pytorch 訓練出來的模型嗎? 如果要應用AI預測,該如何使用呢?

 

是的,Delphi 可以支援使用 Python PyTorch 訓練出來的模型,但需要透過 Python 與 Delphi 的介接將模型轉換為其他格式 來進行應用。以下是幾種常見的方法:


方法 1:透過 Python DLL 介接

將 PyTorch 模型部署為 Python DLL,並透過 Delphi 呼叫 DLL 進行推論。

步驟:

  1. 在 Python 中保存模型並封裝為 DLL

    • 使用 torch.save() 將 PyTorch 模型保存為 .pt.pth 檔案。
    • 使用 ctypespybind11 封裝成 DLL。
    • 範例:

 

 

# save_model.py
import torch
import torch.nn as nn

class SimpleModel(nn.Module):
 def __init__(self):
 super(SimpleModel, self).__init__()
 self.fc = nn.Linear(10, 2)
 
 def forward(self, x):
 return self.fc(x)

model = SimpleModel()
torch.save(model.state_dict(), "model.pth")

 

在 Delphi 中呼叫 Python DLL

  • 使用 LoadLibrary()GetProcAddress() 載入 DLL 並呼叫推論函式。
  • 範例:

 

 

 

function Predict(InputData: PFloatArray): PFloatArray; stdcall; external 'PyModel.dll';

var
 Result: PFloatArray;
begin
 Result := Predict(@InputData);
 ShowMessage('Prediction: ' + FloatToStr(Result^[0]));
end;

優點:

  • 靈活且高效能,可以直接呼叫原生 Python 推論程式碼。
  • 適用於複雜的預測邏輯,例如多步驟預測或序列分析。

缺點:

  • 需要安裝 Python 執行環境,且 DLL 封裝較為繁瑣。
  • 跨平台支援有限,特別是在 macOS 和 Linux 上需要進行額外配置。

方法 2:轉換為 ONNX 格式

將 PyTorch 模型轉換為 ONNX (Open Neural Network Exchange) 格式,再利用 ONNX RuntimeOpenCV DNN 模組 進行推論。

步驟:

  1. 將 PyTorch 模型轉為 ONNX 格式

    • 在 Python 中進行轉換:
import torch
dummy_input = torch.randn(1, 10) # 假設輸入維度為 (1, 10)
torch.onnx.export(model, dummy_input, "model.onnx")

在 Delphi 中使用 OpenCV DNN 模組

  • Delphi 可透過 OpenCV-Pascal 套件來讀取和推論 ONNX 模型。
  • 範例:
uses OpenCV, cvDNN;

var
 Net: TNet;
 InputBlob, OutputBlob: TBlob;
begin
 Net := cvDNN.ReadNetFromONNX('model.onnx');
 InputBlob := cvDNN.BlobFromImage(InputMat);
 Net.SetInput(InputBlob);
 OutputBlob := Net.Forward();
 ShowMessage('Prediction: ' + FloatToStr(OutputBlob.Data[0]));
end;

優點:

  • 跨平台支援良好,可在 Windows、macOS 和 Linux 上執行。
  • 不需安裝 Python 環境,適合封裝成獨立應用程式。

缺點:

  • 需要安裝 OpenCVONNX Runtime 庫,初次設置較為繁瑣。
  • 可能會有 相容性問題,尤其是某些 PyTorch 特定層無法完全轉換為 ONNX。

方法 3:使用 RESTful API 進行推論

將 PyTorch 模型部署於 後端伺服器 (如 Flask、FastAPI),Delphi 則透過 HTTP 請求進行推論

步驟:

  1. 使用 Flask 部署模型服務

    • 部署範例:
from flask import Flask, request, jsonify
import torch
import torch.nn as nn

model = SimpleModel()
model.load_state_dict(torch.load("model.pth"))
model.eval()

app = Flask(__name__)

@app.route('/predict', methods=['POST'])
def predict():
 input_data = request.json['data']
 input_tensor = torch.tensor(input_data)
 with torch.no_grad():
 output = model(input_tensor)
 return jsonify(output.tolist())

if __name__ == '__main__':
 app.run(host='0.0.0.0', port=5000)

在 Delphi 中進行 HTTP 請求

  • 可使用 Indy (IdHTTP)REST.Client 呼叫 API:
uses IdHTTP, System.JSON;

var
 HTTP: TIdHTTP;
 JSONToSend, JSONResponse: TJSONObject;
begin
 HTTP := TIdHTTP.Create(nil);
 try
 JSONToSend := TJSONObject.Create;
 JSONToSend.AddPair('data', '[1.0, 2.0, 3.0, ..., 10.0]');
 JSONResponse := TJSONObject.ParseJSONValue(HTTP.Post('http://localhost:5000/predict', JSONToSend)) as TJSONObject;
 ShowMessage('Prediction: ' + JSONResponse.GetValue('output').Value);
 finally
 HTTP.Free;
 end;
end;

優點:

  • 適用於微服務架構,可以與其他前後端技術整合。
  • 不受語言限制,Delphi 只需進行 HTTP 請求即可。

缺點:

  • 需要維護後端伺服器,增加部署和維護成本。
  • 通訊延遲:推論速度受限於網路和後端效能。

推薦方案:

  • 若需要 高效能且本地化推論,建議選用 方法 2 (ONNX 轉換)
  • 若考慮 微服務或雲端部署,則可使用 方法 3 (RESTful API)
  • 若想直接 調用 Python 模型且不考慮跨平台,則 方法 1 (Python DLL) 會是最靈活的選擇。

你目前是要開發 本地端應用程式 還是 雲端服務?或需要進一步的 Delphi 範例程式碼套件推薦,可以再討論!

 


 

 

"某些 PyTorch 特定層無法完全轉換為 ONNX " 可以針對這個詳細說明嗎?



 

 


 

 

在將 PyTorch 模型轉換為 ONNX 時,確實會遇到某些 特定層或操作無法完全轉換 的問題。這通常是因為 PyTorch 與 ONNX 在運算邏輯和支援的操作上存在差異。以下是詳細說明:


1. 不支援的運算或層 (Unsupported Operators)

說明:

ONNX 的運算支援範圍較廣,但仍有部分 PyTorch 特定的層 (Layer) 或操作 (Operation) 無法直接轉換。例如:

  • 自定義層 (Custom Layers):如自定義的 torch.autograd.Function 或未被 ONNX 社群支援的層。
  • 某些高階操作:例如 torch.einsum()torch.scatter()torch.gather() 的某些參數組合。
  • 部分 Activation 函數:如 SwishMish 等較新的激活函數,可能需要手動轉換。

例子:

 

 

import torch
import torch.nn as nn

class CustomModel(nn.Module):
 def __init__(self):
 super(CustomModel, self).__init__()
 self.linear = nn.Linear(10, 5)
 
 def forward(self, x):
 # einsum 是 ONNX 不支援的操作之一
 return torch.einsum('ij,jk->ik', x, self.linear.weight)

model = CustomModel()
dummy_input = torch.randn(2, 10)
torch.onnx.export(model, dummy_input, "custom_model.onnx")

執行上例時,會出現類似 "Unsupported ONNX operation: Einsum" 的錯誤。


2. 動態控制流 (Dynamic Control Flow)

說明:

ONNX 偏好 靜態計算圖 (Static Computation Graph),而 PyTorch 支援 動態控制流 (Dynamic Control Flow)

  • if 條件判斷、forwhile 迴圈,特別是在迴圈次數依賴於輸入數據時,ONNX 難以轉換。
  • 例如:依據輸入數值大小動態決定層次結構或迴圈次數。

例子:

class DynamicModel(nn.Module):
 def forward(self, x):
 # 根據輸入數值決定迴圈次數
 output = x
 for i in range(x.size(0)):
  output = output + i
 return output

上例中,迴圈次數依賴於 x.size(0),ONNX 會報錯:"Loop condition is not constant"


3. 不支援的 Tensor 操作 (Tensor Operations)

說明:

ONNX 對於部分 Tensor 操作的支援不完整,特別是以下幾種:

  • 複雜的索引操作 (Advanced Indexing):如 x[:, :, ::-1]torch.index_select() 的複雜用法。
  • in-place 操作 (In-place Operations):如 x.add_(y)x *= 2
  • 部分 Broadcasting 操作:PyTorch 支援更靈活的 Broadcasting,而 ONNX 在某些情境下無法完全對應。

例子:

class InplaceModel(nn.Module):
 def forward(self, x):
 # in-place 操作,會被 ONNX 拒絕
 x += 1
 return x

執行轉換時會出現:"Unsupported in-place operation: Add_"


4. 版本相容性問題 (Version Compatibility)

說明:

  • PyTorch 與 ONNX 的版本差異:某些層或操作僅在較新版本中支援,舊版可能無法轉換。
  • ONNX Runtime 的版本限制:即使成功轉換為 ONNX,執行推論時可能因 ONNX Runtime 版本不相容而失敗。

解決方案:

  • 確認版本支援:參考 ONNX 官方支援清單
  • 升級或降級:調整 PyTorch、ONNX、ONNX Runtime 的版本進行測試。

5. 解決方案與建議

  1. 手動重寫不支援的操作:將不支援的部分以 PyTorch 基礎操作重寫 或使用 ONNX 支援的操作 進行等效轉換。

# 將 torch.einsum 重寫為等效的矩陣乘法
def forward(self, x):
 return torch.matmul(x, self.linear.weight.T)
  • 使用 torch.onnx 提供的替代方案

    • 加入 torch.onnx.symbolic_override()torch.onnx.register_custom_op_symbolic() 將不支援的操作替換為 ONNX 支援的操作。
  • 轉換前先檢查模型支援度

    • 使用 torch.onnx.export()verbose=True 參數檢查運算圖,並觀察 UnsupportedWarning 訊息。
    • 使用 ONNX Checker 驗證轉換後的模型:
  • python -c "import onnx; onnx.checker.check_model('model.onnx')"
    1. 考慮其他格式或框架

      • 若無法順利轉換,考慮使用 TorchScriptTensorRTOpenVINO 進行推論。

    總結:

    • PyTorch 與 ONNX 的不相容問題 多數來自 動態控制流自定義層複雜 Tensor 操作版本相容性
    • 建議在開發模型時 儘量選用 ONNX 支援的標準層和操作,並在轉換過程中 逐步 Debug
    • 若需進一步協助 修改模型轉換為其他推論格式,歡迎討論!