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

Visual C++ 視訊影像處理:影像擷取卡整合與畫中畫技術實作

     編輯:關於VC++

前言

電腦視覺應用廣泛,從醫療診斷到工業檢測皆仰賴即時影像處理。本文分享作者使用 VC++ 整合 PCI 影像擷取卡(CA-MPE1000)的實務經驗,涵蓋驅動安裝、調色板設定、影像擷取顯示,並進階實作「畫中畫」技術,解決視訊串流雙畫面閃爍問題。

系統架構與硬體環境

  • 攝影機:BENTECH CV-155L 白黑攝影機 (752x582)
  • 擷取卡:中科院科技嘉 CA-MPE1000 PCI 白黑擷取卡
  • 開發環境:Visual C++ 6.0,廠商提供 mpew32.dll/.lib 函式庫

三步驟整合擷取卡

  1. 安裝驅動程式,將 VxD.vxd 複製到 Windows\SYSTEM。
  2. VC++ 專案連結 mpew32.lib,引入標頭檔宣告初始化、擷取等函式。
  3. 程式碼實作:初始化硬體、設定對比/亮度/水平採樣點、訊號源、PAL 範圍、VGA 模式、分配記憶體緩衝區、設定邏輯調色板、進入擷取迴圈呼叫 W32_ReadXMS2Buf 讀取原始影像資料,再以 SetDIBitsToDevice 顯示。

關鍵程式碼片段

視圖類別建構/解構與初始化

CTestView::CTestView() {
    W32_Init_MPE1000();
    W32_Modify_Contrast(50);
    W32_Modify_Brightness(45);
    W32_Set_HP_Value(945);
    wCurrent_Frame = 1;
    W32_Set_Input_Source(1);
    W32_CACardParam(AD_SETHPFREQ, hpGrabFreq);
    W32_Set_PAL_Range(1250, 1024);
    W32_Set_VGA_Mode(1);
    wGrabWinX1 = wGrabWinY1 = 0;
    bGrabMode = FRAME; bZipMode = ZIPPLE;
    lpDib = NULL; firstTime = TRUE;
}
CTestView::~CTestView() { W32_Close_MPE1000(); }

影像擷取與顯示迴圈


void CTestView::OnGraboneframe() {
    wCurrent_Frame = 1;
    W32_CACardParam(AD_SETGRABDEST, CA_GRABMEM);
    if (lpDib) { GlobalUnlock(hglbDIB); GlobalFree(hglbDIB); }
    hglbDIB = GlobalAlloc(GHND, (DWORD)wImgWidth * wImgHeight);
    lpDib = (BYTE*)GlobalLock(hglbDIB);
    hdc = GetDC()->GetSafeHdc();
    if (lpDib) {
        cxDib = wImgWidth; cyDib = wImgHeight;
        SetLogicPal(hdc, cxDib, cyDib, 8);
        SetStretchBltMode(hdc, COLORONCOLOR);
        bGrabMark = TRUE;
        while (bGrabMark) {
            if (msg.message == WM_LBUTTONDBLCLK) bGrabMark = FALSE;
            W32_ReadXMS2Buf(wCurrent_Frame, lpDib);
            SetDIBitsToDevice(hdc, 0,0, cxDib,cyDib, 0,0, 0,cyDib,
                              (LPSTR)lpDib, bmi, DIB_RGB_COLORS);
        }
        W32_CAStopCapture();
        ::ReleaseDC(GetSafeHwnd(), hdc);
    }
}

調色板與 BITMAPINFO 初始化 (OnSize 中呼叫)


void WINAPI InitLogicPal(HDC hdc, short width, short height, WORD bitCount) {
    LOGPALETTE* pLogPal = (LOGPALETTE*)malloc(sizeof(LOGPALETTE)+256*sizeof(PALETTEENTRY));
    pLogPal->palVersion = 0x300; pLogPal->palNumEntries = 256;
    for (int i=0;i<256;i++) {
        pLogPal->palPalEntry[i].peRed = pLogPal->palPalEntry[i].peGreen = pLogPal->palPalEntry[i].peBlue = i;
        pLogPal->palPalEntry[i].peFlags = 0;
    }
    hPal = CreatePalette(pLogPal); free(pLogPal);
    SelectPalette(hdc, hPal, 0); RealizePalette(hdc);

    bmi = (BITMAPINFO*)malloc(sizeof(BITMAPINFOHEADER)+256*sizeof(RGBQUAD));
    bmi->bmiHeader.biSize=40; bmi->bmiHeader.biWidth=width; bmi->bmiHeader.biHeight=height;
    bmi->bmiHeader.biPlanes=1; bmi->bmiHeader.biBitCount=bitCount; bmi->bmiHeader.biCompression=0;
    for (int i=0;i<256;i++) {
        bmi->bmiColors[i].rgbRed = bmi->bmiColors[i].rgbGreen = bmi->bmiColors[i].rgbBlue = i;
        bmi->bmiColors[i].rgbReserved = 0;
    }
}

畫中畫技術實作

傳統做法先畫大圖再畫小圖會造成視訊串流閃爍。改進方法:使用記憶體 DC (CDC MemDC) 先將大圖與小圖合成離屏,再一次 StretchBlt 輸出螢幕,消除閃爍。


void pictureinpicture() {
    BYTE* pData1 = new char[biWidth*biHeight*3];  // 大圖緩衝
    Read(pData1, biWidth*biHeight*3);             // 從擷取卡讀取
    BITMAPINFO* bmi1 = CreateBMI(24, biWidth, biHeight); // 24-bit RGB

    BYTE* pData2 = new char[biWidth1*biHeight1*3]; // 小圖緩衝 (1/4 或 1/9)
    Read(pData2, biWidth1*biHeight1*3);
    BITMAPINFO* bmi2 = CreateBMI(24, biWidth1, biHeight1);

    CDC MemDC; MemDC.CreateCompatibleDC(&dc);
    CBitmap bmp; bmp.CreateCompatibleBitmap(&dc, biWidth, biHeight);
    CBitmap* pOld = MemDC.SelectObject(&bmp);

    // 1. 大圖畫到記憶體 DC
    StretchDIBits(MemDC.m_hDC, 0,0, biWidth,biHeight, 0,0, -biWidth,biHeight,
                  pData1, bmi1, DIB_RGB_COLORS, SRCCOPY);
    // 2. 小圖疊加在右上角 (20,20)
    StretchDIBits(MemDC.m_hDC, 20,20, biWidth1,biHeight1, 0,0, biWidth1,biHeight1,
                  pData2, bmi2, DIB_RGB_COLORS, SRCCOPY);
    // 3. 一次性輸出螢幕
    StretchBlt(dc.m_hDC, 0,0, biWidth,biHeight, MemDC.m_hDC, 0,0, biWidth,biHeight, SRCCOPY);

    MemDC.SelectObject(pOld);
    delete[] pData1; delete bmi1; delete[] pData2; delete bmi2;
}

結語

透過廠商 SDK 整合擷取卡、自行管理調色板與記憶體 DC 合成,即可在 VC++ 建立高效能視訊處理應用。畫中畫技術關鍵在於離屏合成,避免直接螢幕繪圖造成閃爍,同樣原理可延伸至多畫面監控、ROI 縮放顯示等進階功能。

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