You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于MFC的Basler相机实时预览RetrieveResult报错求助

MFC+Basler Pylon相机实时预览报错排查

我在Visual Studio中使用MFC开发相机接入功能,已创建图片框及「打开」「实时预览」「关闭」按钮:点击「打开」可正常连接相机,「关闭」可断开连接。但点击「实时预览」按钮时,弹出“获取抓取结果失败(failed to retrieve grab result.)”报错,无法实现实时画面预览。已通过Pylon Viewer确认相机连接正常,无法确定问题出在Live按钮逻辑还是帧捕获代码中,附上相关代码恳请排查:

实时预览按钮(Live)代码

void Cimageviewer12Dlg::OnBnClickedButtonLive()
{
    if (!m_isCameraConnected)
    {
        AfxMessageBox(_T("Camera is not connected. Please connect the camera first."));
        return;
    }

    try
    {
        if (!InitializeCamera())
        {
            AfxMessageBox(_T("Failed to initialize camera."));
            return;
        }

        while (true)
        {
            BYTE* pFrameData = nullptr;
            try
            {
                pFrameData = CaptureFrame();
            }
            catch (const GenICam_3_1_Basler_pylon::RuntimeException& e)
            {
                CString errorMsg;
                errorMsg.Format(_T("Failed to capture image from camera: %s"), e.what());
                AfxMessageBox(errorMsg);
                break;
            }

            if (pFrameData == nullptr)
            {
                AfxMessageBox(_T("Failed to capture image from camera."));
                break;
            }

            DisplayFrame(pFrameData);

            if (GetAsyncKeyState(VK_ESCAPE))
                break;

            Sleep(30);
        }
    }
    catch (const GenICam_3_1_Basler_pylon::RuntimeException& e)
    {
        CString errorMsg;
        errorMsg.Format(_T("An error occurred: %s"), e.what());
        AfxMessageBox(errorMsg);
    }

    ReleaseCamera();
}

相机初始化代码

bool Cimageviewer12Dlg::InitializeCamera()
{
    Pylon::PylonInitialize(); // SDK 초기화

    try
    {
        // 카메라 장치 열기
        auto device = CTlFactory::GetInstance().CreateFirstDevice();
        if (device == nullptr)
        {
            AfxMessageBox(_T("Failed to create a device."));
            return false;
        }

        m_camera.Attach(device);
        m_camera.Open();
    
        if (!m_camera.IsOpen())
        {
            AfxMessageBox(_T("Failed to open the camera."));
            return false;
        }

        
    }
    catch (const Pylon::GenericException &e) // 1. 변수 사용
    {
        CString errorMessage;
        errorMessage.Format(_T("Error: %s"), e.GetDescription());
        AfxMessageBox(errorMessage);
        return false;
    }

    return true;  // 초기화 성공 여부 반환
}

帧捕获代码

BYTE* Cimageviewer12Dlg::CaptureFrame()
{
    try
    {
        if (!m_camera.IsOpen())
        {
            AfxMessageBox(_T("Camera is not open."));
            return nullptr;
        }

        // 카메라가 이미 캡처를 시작했는지 확인
        if (!m_camera.IsGrabbing())
        {
            m_camera.StartGrabbing();
            AfxMessageBox(_T("Started grabbing."));
        }

        Pylon::CGrabResultPtr ptrGrabResult;

        // 예외 처리 강화
        m_camera.RetrieveResult(20000, ptrGrabResult, Pylon::TimeoutHandling_ThrowException);

        if (!ptrGrabResult)
        {
            AfxMessageBox(_T("Failed to retrieve grab result."));
            return nullptr;
        }

        if (ptrGrabResult->GrabSucceeded())
        {
            return (BYTE*)ptrGrabResult->GetBuffer();
        }
        else
        {
            CString errorMsg;
            errorMsg.Format(_T("Grab failed: %s"), ptrGrabResult->GetErrorDescription());
            AfxMessageBox(errorMsg);
            return nullptr;
        }
    }
    catch (const Pylon::GenericException &e)
    {
        CString errorMsg;
        errorMsg.Format(_T("An exception occurred: %s"), CString(e.GetDescription()));
        AfxMessageBox(errorMsg);
        return nullptr;
    }
    catch (...)
    {
        AfxMessageBox(_T("An unexpected error occurred."));
        return nullptr;
    }
}

报错截图

报错截图


可能的问题点及修复建议

  • 重复初始化SDK与相机实例冲突
    InitializeCamera()每次调用都执行Pylon::PylonInitialize(),但SDK初始化只需在程序启动时执行一次;同时「打开」按钮已连接相机,Live按钮再次调用InitializeCamera()会重新创建设备并Attach,导致原有实例被覆盖引发抓取异常。
    修复:把PylonInitialize()移到Cimageviewer12Dlg::OnInitDialog()中,InitializeCamera()改为仅在相机未打开时做配置,避免重复Attach设备。

  • 帧缓冲区生命周期失效
    CaptureFrame()返回的ptrGrabResult->GetBuffer()指针,会在函数结束后随局部变量ptrGrabResult被销毁,导致DisplayFrame()访问非法内存,甚至引发后续抓取异常。
    修复:在DisplayFrame()内完成帧数据拷贝,或者将CGrabResultPtr设为类成员变量延长生命周期。

  • UI线程阻塞导致抓取超时
    Live按钮的while循环直接在UI线程执行,Sleep(30)会阻塞UI消息循环,相机事件处理不及时引发超时错误。
    修复:把抓取逻辑放到独立工作线程,通过消息机制将帧数据传给UI线程显示。

  • 未配置连续抓取模式
    默认情况下相机可能是单帧抓取模式,需要在InitializeCamera()中添加配置:

    m_camera.PixelFormat.SetValue(Pylon::PixelFormat_Mono8); // 按相机实际格式调整
    m_camera.AcquisitionMode.SetValue(Pylon::AcquisitionMode_Continuous);
    
  • 异常捕获范围不全
    当前代码仅捕获RuntimeException,建议统一捕获Pylon::GenericException覆盖所有Pylon SDK异常。

内容的提问来源于stack exchange,提问作者Sanghyeon Woo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 10:36:00