MFC,C++,海康SDK,回调,轮询

二次开发,但是找遍了所有的技术文档,都没有找到实现回调取图的完整流程的教程,文档。痛苦不堪,虽然轮询取图在技术文档中实现了,但是还是需要将其与其他很多功能分开。特此,本文将再次简单记录一下实现的过程。

1.一定要使用面向对象的方式。

创建一个相机类和一个主框架类,这里直接在其技术文件中可以找到复制粘贴即可。

然后现在讲述回调实现的源码。轮询技术文档提供,不赘述.

1. 修改对话框类头文件

首先在CImage_GrabDlg.h中添加必要的成员变量和函数声明:

cpp 复制代码
// Image_GrabDlg.h
class CImage_GrabDlg : public CDialogEx
{
    // ... 其他已有代码
    
protected:
    // 用于显示图像的静态控件句柄
    HWND m_hwndDisplay;
    
    // 图像数据相关
    unsigned char* m_pSaveImageBuf;
    unsigned int m_nSaveImageBufSize;
    CRITICAL_SECTION m_hSaveImageMux;
    MV_FRAME_OUT_INFO_EX m_stImageInfo;
    
    // 回调函数声明
    static void __stdcall ImageCallBackEx(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser);
    void OnImageCallBack(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo);
    
    // 初始化函数
    void DisplayWindowInitial();
    
    // ... 其他已有成员
};

2. 修改对话框类实现文件

2.1 初始化部分

cpp 复制代码
// Image_GrabDlg.cpp
CImage_GrabDlg::CImage_GrabDlg(CWnd* pParent /*=NULL*/)
    : CDialogEx(IDD_IMAGE_GRAB_DIALOG, pParent)
    , m_pcMyCamera(NULL)
    , m_nDeviceCombo(0)
    , m_bOpenDevice(FALSE)
    , m_bStartGrabbing(FALSE)
    , m_hGrabThread(NULL)
    , m_bThreadState(FALSE)
    , m_nTriggerMode(MV_TRIGGER_MODE_OFF)
    , m_pSaveImageBuf(NULL)
    , m_nSaveImageBufSize(0)
{
    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
    memset(&m_stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
    InitializeCriticalSection(&m_hSaveImageMux);
}

CImage_GrabDlg::~CImage_GrabDlg()
{
    DeleteCriticalSection(&m_hSaveImageMux);
    if (m_pSaveImageBuf)
    {
        free(m_pSaveImageBuf);
        m_pSaveImageBuf = NULL;
    }
}

2.2 回调函数实现

cpp 复制代码
// 静态回调函数
void __stdcall CImage_GrabDlg::ImageCallBackEx(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo, void* pUser)
{
    if (!pData || !pFrameInfo || !pUser)
    {
        return;
    }
    
    CImage_GrabDlg* pThis = (CImage_GrabDlg*)pUser;
    pThis->OnImageCallBack(pData, pFrameInfo);
}

// 实际处理回调的成员函数
void CImage_GrabDlg::OnImageCallBack(unsigned char* pData, MV_FRAME_OUT_INFO_EX* pFrameInfo)
{
    // 保存图像数据
    EnterCriticalSection(&m_hSaveImageMux);
    
    if (NULL == m_pSaveImageBuf || pFrameInfo->nFrameLen > m_nSaveImageBufSize)
    {
        if (m_pSaveImageBuf)
        {
            free(m_pSaveImageBuf);
            m_pSaveImageBuf = NULL;
        }
        
        m_pSaveImageBuf = (unsigned char*)malloc(pFrameInfo->nFrameLen);
        if (m_pSaveImageBuf == NULL)
        {
            LeaveCriticalSection(&m_hSaveImageMux);
            return;
        }
        m_nSaveImageBufSize = pFrameInfo->nFrameLen;
    }
    
    memcpy(m_pSaveImageBuf, pData, pFrameInfo->nFrameLen);
    memcpy(&m_stImageInfo, pFrameInfo, sizeof(MV_FRAME_OUT_INFO_EX));
    
    LeaveCriticalSection(&m_hSaveImageMux);
    
    // 在UI线程中更新显示
    if (m_hwndDisplay)
    {
        MV_CC_IMAGE stImageData = {0};
        stImageData.nWidth = pFrameInfo->nWidth;
        stImageData.nHeight = pFrameInfo->nHeight;
        stImageData.enPixelType = pFrameInfo->enPixelType;
        stImageData.nImageLen = pFrameInfo->nFrameLen;
        stImageData.pImageBuf = pData;
        
        m_pcMyCamera->DisplayOneFrame(m_hwndDisplay, &stImageData);
    }
}

2.3 开始采集按钮实现

cpp 复制代码
void CImage_GrabDlg::OnBnClickedButton4()
{
    if (FALSE == m_bOpenDevice || TRUE == m_bStartGrabbing || NULL == m_pcMyCamera)
    {
        return;
    }

    // 注册回调函数
    int nRet = MV_CC_RegisterImageCallBackEx(m_pcMyCamera->outinterface(), CImage_GrabDlg::ImageCallBackEx, this);
    if (MV_OK != nRet)
    {
        ShowErrorMsg(TEXT("Register image callback fail"), nRet);
        return;
    }

    // 设置采集模式为连续采集
    nRet = m_pcMyCamera->SetNetTransMode(MV_TRIGGER_MODE_OFF);
    if (MV_OK != nRet)
    {
        ShowErrorMsg(TEXT("Set trigger mode fail"), nRet);
        return;
    }

    // 开始采集
    nRet = m_pcMyCamera->StartGrabbing();
    if (MV_OK != nRet)
    {
        ShowErrorMsg(TEXT("Start grabbing fail"), nRet);
        return;
    }

    m_bStartGrabbing = TRUE;
}

2.4 停止采集按钮实现

cpp 复制代码
void CImage_GrabDlg::OnBnClickedButton6()
{
    if (FALSE == m_bOpenDevice || FALSE == m_bStartGrabbing || NULL == m_pcMyCamera)
    {
        return;
    }

    // 停止采集
    int nRet = m_pcMyCamera->StopGrabbing();
    if (MV_OK != nRet)
    {
        ShowErrorMsg(TEXT("Stop grabbing fail"), nRet);
        return;
    }

    // 注销回调函数
    nRet = MV_CC_RegisterImageCallBackEx(m_pcMyCamera->outinterface(), NULL, NULL);
    if (MV_OK != nRet)
    {
        ShowErrorMsg(TEXT("Unregister image callback fail"), nRet);
    }

    m_bStartGrabbing = FALSE;
}

3. 显示窗口初始化

cpp 复制代码
void CImage_GrabDlg::DisplayWindowInitial()
{
    CWnd *pWnd = GetDlgItem(IDC_DISPLAY_STATIC);
    if (pWnd)
    {
        m_hwndDisplay = pWnd->GetSafeHwnd();
        
        // 设置静态控件样式为SS_BITMAP,用于显示图像
        pWnd->ModifyStyle(0, SS_BITMAP);
        
        // 初始化显示黑色背景
        CRect rect;
        pWnd->GetClientRect(&rect);
        CDC *pDC = pWnd->GetDC();
        CBitmap bitmap;
        bitmap.CreateCompatibleBitmap(pDC, rect.Width(), rect.Height());
        pWnd->SetBitmap((HBITMAP)bitmap.Detach());
        pWnd->ReleaseDC(pDC);
    }
}

4. 资源文件修改

在对话框资源中添加一个静态文本控件,ID设置为IDC_DISPLAY_STATIC,用于显示图像。调整其大小以适应图像显示需求。

5. 使用说明

  1. 点击"查找设备"按钮枚举可用相机设备

  2. 选择设备后点击"打开设备"按钮连接相机

  3. 点击"开始采集"按钮开始接收图像并在静态控件中显示

  4. 点击"停止采集"按钮停止图像采集

  5. 点击"关闭设备"按钮断开相机连接

注意事项

  1. 图像显示使用了静态控件的SS_BITMAP样式,确保控件足够大以显示完整图像

  2. 使用了临界区保护图像数据,确保多线程安全

  3. 回调函数中直接调用显示函数,确保图像实时显示

  4. 需要处理图像格式转换,如果相机输出的像素格式与显示要求不符

这个方案利用了海康威视相机SDK的回调机制,在回调函数中获取图像数据并显示在MFC对话框的静态控件中,实现了高效的图像采集和显示功能。

最后注意,上述一定是在类中实现的,如果没有类的基础,上述可能对你没有什么帮助,当然如果自己实在使用不上上面给出的思路,可以在评论区,评论,博主看到会简答。

相关推荐
minji...8 分钟前
C++ string类(STL简介 , string类 , 访问修改字符)
开发语言·c++
Forward♞14 分钟前
Qt——文件操作
开发语言·c++·qt
十五年专注C++开发33 分钟前
CMake进阶: CMake Modules---简化CMake配置的利器
linux·c++·windows·cmake·自动化构建
老虎06271 小时前
JavaWeb前端02(JavaScript)
开发语言·前端·javascript
Python私教1 小时前
YggJS RLogin暗黑霓虹主题登录注册页面 版本:v0.1.1
开发语言·javascript·ecmascript
winds~2 小时前
【git】 撤销revert一次commit中的某几个文件
linux·c++
芒果很香2 小时前
MFC中使用EXCEL的方法之一
excel·mfc
王廷胡_白嫖帝2 小时前
Qt猜数字游戏项目开发教程 - 从零开始构建趣味小游戏
开发语言·qt·游戏
XH华2 小时前
C语言第九章字符函数和字符串函数
c语言·开发语言