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对话框的静态控件中,实现了高效的图像采集和显示功能。

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

相关推荐
荒川之神27 分钟前
拉链表概念与基本设计
java·开发语言·数据库
chushiyunen37 分钟前
python中的@Property和@Setter
java·开发语言·python
小樱花的樱花43 分钟前
C++ new和delete用法详解
linux·开发语言·c++
froginwe111 小时前
C 运算符
开发语言
fengfuyao9851 小时前
低数据极限下模型预测控制的非线性动力学的稀疏识别 MATLAB实现
开发语言·matlab
摇滚侠1 小时前
搭建前端开发环境 安装 nodejs 设置淘宝镜像 最简化最标准版本 不使用 NVM NVM 高版本无法安装低版本 nodejs
java·开发语言·node.js
t198751282 小时前
MATLAB十字路口车辆通行情况模拟系统
开发语言·matlab
yyk的萌2 小时前
AI 应用开发工程师基础学习计划
开发语言·python·学习·ai·lua
Amumu121383 小时前
Js:正则表达式(一)
开发语言·javascript·正则表达式
努力的章鱼bro3 小时前
操作系统-FileSystem
c++·操作系统·risc-v·filesystem