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

利用 VFW 在 Delphi 中開發視訊擷取程式:完整實作指南

     編輯:Delphi

前言:視訊擷取技術的關鍵角色

在現代圖像處理系統中,視訊擷取與即時處理堪稱核心關鍵技術。能否精準擷取指定視訊影像,進而實現精確的資料分析與處理,直接關係到整個系統的成敗。筆者在開發「公路安全線軋壓檢測系統」時深有體會:該系統旨在監測關鍵路段車輛是否瞬間軋壓黃色安全線,透過即時拍攝、抓取瞬間影像,經系統分析處理後及時檢測車輛行駛狀況,進而驅動控制設備做出相應處理。顯然,即時擷取視訊影像是系統的命脈所在。

為何選擇 Microsoft VFW 技術

為解決即時視訊擷取需求,筆者採用 Microsoft 推出的 Video for Windows (VFW) 技術。VFW 讓應用程式能透過數位化設備從傳統類比視訊源取得數位視訊片段,其核心優在於播放時不需專用硬體。針對數位視訊資料量龐大的問題,VFW 引入 AVI 檔案標準,規範視訊與音訊在硬碟及 AVI 檔案中的交替儲存方式。VFW 更提供標準介面,讓程式設計師透過發送訊息或設定屬性即可擷取、播放與編輯視訊片段。安裝 VFW 時會自動配置所需組件(裝置驅動程式、視訊壓縮程式等),主要包含六大功能模組:

模組功能
AVICAP.DLL包含視訊擷取函數,為 AVI 檔案 I/O 處理及視訊/音訊裝置驅動提供高階介面
MSVIDEO.DLL含特殊 DrawDib 函數,處理螢幕視訊操作
MCIAVI.DRVVFW MCI 命令解譯器驅動程式
AVIFILE.DLL提供標準多媒體 I/O (mmio) 更高層命令,存取 .AVI 檔案
ICM壓縮管理器,管理視訊壓縮/解壓縮編碼器 (Codec)
ACM音訊壓縮管理器,提供類似 ICM 服務,適用波形音訊

視訊擷取程式開發四大核心步驟

2.1 運用 AVICap 視窗類別

本文採用 AVICap 視窗類別開發視訊擷取程式。AVICap 支援即時視訊串流擷取與單幀擷取,並提供視訊源控制。雖然常用的 MCI 控制項也提供數位視訊服務,但其命令主要基於檔案操作,無法滿足即時從視訊緩衝區提取資料的需求。對於無視訊疊加能力捕獲卡的 PC,MCI 更無法擷取視訊串流。AVICap 優勢在於能直接存取視訊緩衝區,無需產生中間檔案,即時性強、效率高,亦可將數位視訊擷取至檔案中。

2.2 開發基本流程

  1. 建立「擷取視窗」:視訊擷取前必須先建立擷取視窗,作為所有擷取與設定操作的基礎。使用 AVICap 的 capCreateCaptureWindow 函數建立,視窗樣式設為 WS_CHILD 和 WS_VISIBLE。擷取視窗功能涵蓋:擷取視訊/音訊串流至 AVI 檔案、動態連接/斷開輸入裝置、Overlay 或 Preview 模式即時顯示、指定檔案名與複製擷取內容、設定擷取速率、顯示控制對話框、建立/儲存/載入調色盤、複製影像至剪貼簿、儲存單幀影像為 DIB 格式等。
  2. 關聯擷取視窗與驅動程式:單獨的擷取視窗無法運作,必須透過 capDriverConnect 函數與裝置驅動程式關聯,才能取得視訊訊號。
  3. 設定視訊裝置屬性:透過設定 TCaptureParms 結構成員變數,控制取樣頻率、中斷取樣按鍵、狀態列行為。設定完成後用 capCaptureSetSetup 生效,再以 capPreviewScale、capPreviewRate 設定預覽比例與速度,或採用裝置預設值。
  4. 開啟預覽:用 capOverlay 選擇是否採用疊加模式預覽(減少系統資源佔用、加快顯示速度),再以 capPreview 啟動預覽,即可在螢幕看見攝影機影像。

若需自行處理擷取的視訊資料,則須使用擷取視窗回呼函數,如逐幀取得視訊資料或串流方式取得資料。

Delphi 視訊擷取程式實作範例

針對系統存取與處理速度的特殊需求,筆者選用 Delphi 為開發工具。以下以逐幀從視訊裝置擷取視訊資料的程式為例,說明各函數作用與具體開發過程。範例功能:螢幕顯示擷取視訊,並可取得每幀影像資料。

實作步驟

  1. 新建專案,將 AVICAP32.PAS 加入 uses 子句。
  2. 在 Form1 放置一個 TPanel(Name 設為 gCapVideoArea,用於顯示視訊),及兩個 TButton(OpenVideo、CloseVideo)。
  3. 定義全域變數:
    ghCapWnd: THandle;        // 擷取視窗控制代碼
    VideoStr: LPVIDEOHDR;     // 取得視訊資料指標的結構,用於回呼函數
    CapParms: TCaptureParms;  // 設定裝置屬性的結構變數
    
  4. 編寫 OpenVideo 按鈕 OnClick 事件程式碼:
    procedure TForm1.OpenVideoClick(Sender: TObject);
    begin
      // 使用 TPanel 建立擷取視窗
      ghCapWnd := capCreateCaptureWindow(PChar('KruwoSoft'),
        WS_CHILD or WS_VISIBLE, 0, 0,
        gCapVideoArea.Width, gCapVideoArea.Handle, 0);
    
      // 設定回呼函數
      capSetCallbackOnVideoStream(ghCapWnd, @VideoStreamCallBack); // 擷取視訊串流
      capSetCallbackOnError(ghCapWnd, @ErrorCallBack);             // 取得裝置錯誤
      capSetCallbackOnStatus(ghCapWnd, @StatusCallBack);           // 取得裝置狀態
      capSetCallbackOnFrame(ghCapWnd, @FrameCallBack);             // 幀擷取回呼
    
      // 關聯擷取視窗與裝置驅動 (參數 0 為第一個裝置)
      capDriverConnect(ghCapWnd, 0);
    
      // 設定擷取參數
      CapParms.dwRequestMicroSecPerFrame := 40000;  // 25 fps
      CapParms.fLimitEnabled      := FALSE;
      CapParms.fCaptureAudio      := FALSE;         // 無音訊
      CapParms.fMCIControl        := FALSE;
      CapParms.fYield             := TRUE;
      CapParms.vKeyAbort          := VK_ESCAPE;
      CapParms.fAbortLeftMouse    := FALSE;
      CapParms.fAbortRightMouse   := FALSE;
      capCaptureSetSetup(ghCapWnd, @CapParms, SizeOf(TCaptureParms));
    
      capPreviewScale(ghCapWnd, 1);
      capPreviewRate(ghCapWnd, 66);
    
      // 不產生 AVI 檔案,直接擷取串流
      capCaptureSequenceNoFile(ghCapWnd);
    
      // 啟用疊加模式並開始預覽
      capOverlay(ghCapWnd, 1);
      capPreview(ghCapWnd, 1);
    end;
    
  5. 編寫 CloseVideo 按鈕 OnClick 事件:
    procedure TForm1.CloseVideoClick(Sender: TObject);
    begin
      capCaptureAbort(ghCapWnd);     // 停止擷取
      capDriverDisconnect(ghCapWnd); // 斷開擷取視窗與驅動
    end;
    
  6. 定義幀擷取回呼函數:
    function FrameCallBack(hWnd: HWND; lpVHdr: LongInt): LongInt; stdcall;
    var
      DataPoint: ^Byte;
      DibLen, RectWidth, RectHeight: Integer;
    begin
      VideoStr := LPVIDEOHDR(lpVHdr);
      DibLen := VideoStr^.dwBufferLength;
      GetMem(DataPoint, 64000);
      // 複製幀資料到記憶體 (DataPoint 需預先配置空間)
      CopyMemory(DataPoint, VideoStr^.lpData, DibLen);
      // 此處可進一步處理影像資料...
      Result := 1;
    end;
    

結語與注意事項

靈活運用 AVICap 視窗類別的回呼函數可滿足多樣化需求,但須注意:從視訊卡擷取的視訊資料格式與影像長寬需參考視訊卡參數。部分視訊卡支援多種格式與解析度,還原影像時務必依據實際使用的視訊卡參數設定,以確保影像正確顯示與處理。

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