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

OpenCV + 海康威視攝像頭實時讀取(SDK + 回調 + 多線程)

     編輯:關於C++

一、環境準備

  • 硬件:PC (i7, 16GB),海康攝像頭 DS-2CD3310D-I
  • 軟件:Windows x64, VS2012, OpenCV 2.4.8, 海康 SDK 5.1.1.4 (x64)

二、配置步驟

  1. 用 SADP 工具設定攝像頭 IP 與 PC 同網段。
  2. 瀏覽器訪問攝像頭 IP(默認 admin / a123456789),安裝 Web 控件。
  3. 用 SDK 自帶 ClientDemo.exe 驗證可正常預覽。
  4. VS 配置:包含目錄、庫目錄、依賴項(HCNetSDK.lib, PlayCtrl.lib, ws2_32.lib 等)。

三、核心代碼流程(C++)

關鍵點:

  • 初始化 SDK、設置重連
  • 登錄設備 NET_DVR_Login_V30
  • 啟動預覽 NET_DVR_RealPlay_V30,註冊碼流回調 fRealDataCallBack
  • 回調中獲取系統頭、碼流數據,調用播放庫 PlayM4 解碼
  • 解碼回調 DecCBFun 中將 YV12 轉 RGB,存入全局幀隊列 g_frameList(加鎖保護)
  • 主線程從隊列取幀進一步處理/顯示

關鍵代碼片段

// 解碼回調:YV12 轉 RGB
void CALLBACK DecCBFun(long nPort, char* pBuf, long nSize, FRAME_INFO* pFrameInfo, ...) {
    if (pFrameInfo->nType == T_YV12) {
        // YV12 轉 YUV (IplImage)
        // cvCvtColor YCrCb2RGB
        Mat frame(pImg); // 轉 Mat
        EnterCriticalSection(&g_cs_frameList);
        g_frameList.push_back(frame);
        LeaveCriticalSection(&g_cs_frameList);
    }
}

// 碼流回調:送入播放庫
void CALLBACK fRealDataCallBack(LONG lRealHandle, DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize, ...) {
    switch (dwDataType) {
        case NET_DVR_SYSHEAD:
            PlayM4_GetPort(&nPort);
            PlayM4_OpenStream(nPort, pBuffer, dwBufSize, 1024*1024);
            PlayM4_SetDecCallBack(nPort, DecCBFun);
            PlayM4_Play(nPort, hWnd);
            break;
        case NET_DVR_STREAMDATA:
            PlayM4_InputData(nPort, pBuffer, dwBufSize);
            break;
    }
}

// 主函數:啟動讀取線程,主循環取幀
unsigned readCamera(void* param) {
    NET_DVR_Init();
    NET_DVR_SetConnectTime(2000, 1);
    NET_DVR_SetReconnect(10000, true);
    LONG lUserID = NET_DVR_Login_V30("192.168.2.64", 8000, "admin", "a123456789", &struDeviceInfo);
    NET_DVR_SetExceptionCallBack_V30(0, NULL, g_ExceptionCallBack, NULL);
    NET_DVR_CLIENTINFO ClientInfo = {1, NULL, 0, NULL};
    LONG lRealPlayHandle = NET_DVR_RealPlay_V30(lUserID, &ClientInfo, fRealDataCallBack, NULL, TRUE);
    Sleep(-1); // 保持線程
    // 清理...
    return 0;
}

int main() {
    InitializeCriticalSection(&g_cs_frameList);
    _beginthreadex(NULL, 0, readCamera, NULL, 0, &threadID);
    while (true) {
        EnterCriticalSection(&g_cs_frameList);
        if (!g_frameList.empty()) {
            Mat frame = g_frameList.front(); g_frameList.pop_front();
            // imshow / 處理
        }
        LeaveCriticalSection(&g_cs_frameList);
    }
}

四、注意事項

  • 64 位環境需用 x64 版 SDK 和 OpenCV
  • 幀隊列需線程安全(CriticalSection 或 mutex)
  • 及時釋放 IplImage/Mat 避免內存洩漏
  • 異常回調處理斷線重連
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved