基于MFC的Basler相机实时预览RetrieveResult报错求助
我在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

