首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> Delphi

Delphi 實作 Lucas-Kanade 光流演算法:特徵點追蹤與金字塔優化完整類別

     編輯:Delphi

前言

Lucas-Kanade 光流法 是電腦視覺中經典的稀疏光流追蹤演算法,廣泛應用於物件追蹤、動作分析與視覺里程計。本文介紹一個完整的 Delphi 類別 TOpticalFlowLK,實作了特徵點偵測(Good Features to Track)、影像金字塔建構、多層級光流計算與結果視覺化繪製。

核心架構設計

類別定義與關鍵資料結構

type
  TOpticalFlowLK = class
  private
    // 影像金字塔儲存:舊幀、新幀、灰階、梯度、特徵值、角點標記
    ImageOld, ImageNew: TTripleLongintArray;
    ImageGray, dx, dy, dxy: TDoubleLongintArray;
    Eigenvalues: TDoubleExtendedArray;
    WBPoint: TDoubleBooleanArray;
    Height, Width, L, RadioX, RadioY: Longint;
    procedure CornerDetect(sWidth, sHeight: Longint; Quality: Extended);
    procedure MakePyramid(var Images: TTripleLongintArray; sWidth, sHeight, sL: Longint);
  public
    Frame: TBitmap;                    // 繪製結果畫布
    Features: TSinglePointInfoArray;   // 特徵點陣列
    FeatureCount, SupportCount: Longint;
    Speed, Radio: Extended;            // 平均速度與方向
    procedure Init(sWidth, sHeight, sL: Longint);
    procedure InitFeatures(Frames: TBitmap);
    procedure CalOpticalFlowLK(Frames: TBitmap);
    destructor Destroy; override;
  end;

關鍵演算法流程

1. 特徵點偵測 - Shi-Tomasi 角點檢測

採用 Good Features to Track (CVPR 1994) 方法:

  • 計算 Sobel 梯度 dx, dy, dxy
  • 構建 3x3 窗口內的二階矩陣 M,計算最小特徵值 λ_min
  • 非極大值抑制(Non-maximum Suppression)移除鄰域內較弱角點
// 核心特徵值計算
Eigenvalues[i, j] := (a + c - Sqrt((a - c)*(a - c) + b*b));
// 閾值篩選
MinAccept := MaxEigenvalue * Quality;
// 非極大值抑制:17x17 窗口內保留局部最大值
if (Eigenvalues[fi, fj] >= sum) and ((fi <> i) or (fj <> j)) then
  WBPoint[i, j] := False;

2. 影像金字塔建構

使用高斯金字塔下採樣(5x5 核近似),每層解析度減半:

procedure TOpticalFlowLK.MakePyramid(var Images: TTripleLongintArray; ...);
begin
  for k := 1 to sL - 1 do begin
    nWidth := (oWidth + 1) shr 1;
    // 高斯加權平均:中心權重 4/16,邊緣 2/16,角落 1/16
    Images[i, j, k] := (Images[ii, jj, k-1] shl 2 + ... ) shr 4;
    // 邊界特殊處理...
  end;
end;

3. 多層級 Lucas-Kanade 光流計算

參考 Bouguet 的金字塔實作,從粗到精迭代優化:

for ll := L - 1 downto 0 do begin
  // 計算梯度矩陣 G = [ΣIx², ΣIxIy; ΣIxIy, ΣIy²]
  // 迭代求解位移向量 d = G⁻¹ * b
  for k := 1 to 10 do begin
    Ik := ImageOld[i, j, ll] - ImageNew[kx, ky, ll];
    // 更新位移向量...
  end;
  // 位移向量傳遞至下一層:g_{l-1} = 2 * (g_l + d_l)
end;

4. 結果視覺化與統計

  • 綠色圓圈標記特徵點位置
  • 黃色線段顯示位移向量
  • 藍色箭頭指示整體運動方向,紅點標記端點
  • 計算平均速度與主方向角度

使用範例

var
  LK: TOpticalFlowLK;
  Frame: TBitmap;
begin
  LK := TOpticalFlowLK.Create;
  try
    LK.Init(640, 480, 3);        // 寬、高、金字塔層數
    LK.InitFeatures(FirstFrame); // 初始化首幀特徵點
    while Video.HasNext do begin
      Frame := Video.GetNextFrame;
      LK.CalOpticalFlowLK(Frame); // 計算光流
      // LK.Frame 即為繪製好結果的畫布
      Canvas.Draw(0, 0, LK.Frame);
    end;
  finally
    LK.Free;
  end;
end;

效能考量與優化建議

  • 金字塔層數 L 建議 3~5 層,平衡精度與速度
  • 特徵點數量由 Quality 參數控制,典型值 0.01~0.05
  • 大量浮點運算建議開啟 {$O+} 優化並使用 Double 而非 Extended
  • 可考慮使用 SIMD 指令集或 GPU 加速核心迴圈

結語

此實作提供了完整、可直接整合的 Delphi 光流追蹤元件,適合即時視訊分析、機器人導航與人機互動等應用。程式碼結構清晰,便於依據專案需求擴展特徵點管理、異常值過濾或卡爾曼濾波器整合。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved