現代光學測量技術融合了光電子、計算機、激光及圖像處理等學科,廣泛應用於幾何量測量、航空遙感、精密零件檢測等領域。在基於數字圖像處理的測量系統中,圖像采集是首要環節,其實時性與數據質量直接決定後續處理的成敗。本文針對 VC++ 6.0 環境下利用 Video for Windows (VFW) 技術實現視頻實時采集時遇到的三大核心問題進行深度探討並給出解決方案。
VC++ 6.0 提供 MCIAVI、DRAWDIB、AVIFILE、AVICAP 等組件,協同完成播放、編輯、文件管理及視頻捕獲。AVICAP 通過 AVICap32.dll 創建捕獲窗口類,利用消息、宏函數、結構及回調函數驅動采集流程。其優勢在於:
主要采集模式包括:序列捕獲到文件、序列捕獲到緩衝、單幀捕獲、本地預覽、單幀預覽等。VFW 還提供回調機制,允許在幀間隙或新幀到達時精確處理實時數據。
嘗試定義非靜態成員函數作為回調:
LRESULT CALLBACK FrameCallbackProc(HWND ghWnd, LPVIDEOHDR lpVData) { ... }
編譯報錯,原因在於 C++ 非靜態成員函數隱含 this 指針,導致函數簽名與 SDK 期望的 CALLBACK 規約不匹配。
friend,可訪問私有成員。此法本質同純 C 编程。class CMyClass {
static CMyClass* s_pThis; // 靜態指針
static LRESULT CALLBACK FrameCallbackProc(HWND hWnd, LPVIDEOHDR lpVData) {
// 通過 s_pThis 訪問實例成員
return s_pThis->OnFrameCallback(hWnd, lpVData);
}
LRESULT OnFrameCallback(HWND hWnd, LPVIDEOHDR lpVData) { ... } // 實際處理邏輯
};
// 構造函數中初始化:s_pThis = this;
注意:單例模式下此法完美;多實例需利用回調參數傳遞 this 指針(如 lpVData->dwUser),稍顯複雜。
部分采集卡驅動在回調數據中強制壓縮(如 DC10),破壞測量精度。兩種獲取無壓縮幀數據的方法:
capGrabFrameNoStop() 抓幀 → capEditCopy() 複製到剪貼板(此過程不壓縮) → 以 CF_DIB 格式從剪貼板讀取句柄 → 操作 DIB 獲取像素首地址。代碼片段:
HANDLE hData = CopyHandle(::GetClipboardData(CF_DIB));
// 操作 hData 獲取 BITMAPINFOHEADER 及像素指針
capFileSaveDIB() 直接保存為 BMP 文件 → 再讀入內存處理。雖有磁盤 I/O 開銷,但對計算量不大的算法仍能滿足實時要求。捕獲窗口是所有操作的基礎,其父窗口句柄的獲取隨框架類型(SDI、MDI、對話框)而異。兩種典型創建方式:
m_hWnd 作為捕獲窗父窗口。
CFrameWnd m_wndSource;
m_wndSource.CreateEx(WS_EX_TOPMOST, NULL, _T("source"), WS_CAPTION, CRect(100,100,150,180), NULL, 0);
m_wndSource.ShowWindow(SW_HIDE);
m_WndCap = capCreateCaptureWindow(_T("視頻捕捉"), WS_CHILD|WS_VISIBLE, 0,0,300,240, m_wndSource.m_hWnd, 0);
m_hWnd 為父窗口,捕獲窗顯示於客戶區內。
m_hCapWnd = capCreateCaptureWindow(_T("視頻捕捉"), WS_CHILD|WS_VISIBLE, 0,0,768,576, this->m_hWnd, 0);
VFW 技術顯著提升了視頻采集的效率與靈活性,解決了硬件依賴難題。本文針對回調函數定義、數據壓縮繞過、窗口創建適配三大實戰痛點給出了成熟方案,已在多個工業測量系統中驗證穩定可靠。