工业相机帧率获取(C++ 版本)
附海康 / Basler / 堡盟三大品牌完整代码,精准掌握实时 FPS!
“我的相机标称 120fps,为什么程序里只跑出 40fps?”
“如何在 C++ 应用中实时显示当前帧率?”
“不同品牌 SDK 获取帧率的方式天差地别?”
在高性能工业视觉系统中,帧率(FPS)是衡量系统吞吐能力的黄金指标。它直接决定了产线的检测节拍和效率。
本文将深入 C++ 层面,为你提供海康(Hikvision)、Basler、堡盟(Baumer)三大主流工业相机的实时帧率获取方案,并附上可直接编译运行的代码。
📊 一、帧率的两种类型(C++ 视角)
| 类型 | 说明 | 获取方式 |
|---|---|---|
| 理论帧率 (Max FPS) | 相机在当前配置下能达到的上限 | 通过 SDK 查询AcquisitionFrameRate等参数 |
| 实际帧率 (Real FPS) | 应用真正处理图像的速率 | 需通过高精度计时 + 帧计数计算 |
💡本文核心:获取「实际帧率」,因为它反映了你 C++ 程序的真实性能。
⏱️ 二、通用帧率计算器(C++17)
我们首先实现一个跨平台、高精度的帧率计算器:
// FrameRateCounter.h#pragmaonce#include<chrono>#include<atomic>classFrameRateCounter{public:voidOnNewFrame(){++frameCount_;}doubleGetFPS(){autonow=std::chrono::steady_clock::now();autoelapsed=std::chrono::duration_cast<std::chrono::microseconds>(now-lastTime_).count();if(elapsed>=1'000'000){// 1 secondfps_=static_cast<double>(frameCount_.exchange(0))*1'000'000.0/elapsed;lastTime_=now;}returnfps_;}private:std::atomic<uint64_t>frameCount_{0};std::chrono::steady_clock::time_point lastTime_=std::chrono::steady_clock::now();doublefps_=0.0;};🔧 三、各品牌 SDK 实战代码(C++)
1. 海康(Hikvision)MVS C++ SDK
// HikvisionFPS.cpp#include"MVCameraControl.h"#include"FrameRateCounter.h"#include<iostream>#include<thread>classHikvisionCamera{public:boolOpenCamera(){MV_CC_DEVICE_INFO_LIST stDevList;MV_CC_EnumDevices(MV_GIGE_DEVICE,&stDevList);if(stDevList.nDeviceNum>0){MV_CC_CreateHandle(&handle_,stDevList.pDeviceInfo[0]);returnMV_CC_OpenDevice(handle_)==MV_OK;}returnfalse;}voidStartGrabbing(){MV_CC_SetEnumValue(handle_,"TriggerMode",MV_TRIGGER_MODE_OFF);MV_CC_StartGrabbing(handle_);// 启动取图线程grabThread_=std::thread([this](){MV_FRAME_OUT_INFO_EX stImageInfo={0};unsignedchar*pData=newunsignedchar[1920*1200*3];while(running_){intnRet=MV_CC_GetOneFrameTimeout(handle_,pData,1920*1200*3,&stImageInfo,1000);if(nRet==MV_OK){fpsCounter_.OnNewFrame();// 关键:通知帧率计数器// 处理图像...}}delete[]pData;});}doubleGetFPS(){returnfpsCounter_.GetFPS();}~HikvisionCamera(){running_=false;if(grabThread_.joinable())grabThread_.join();if(handle_){MV_CC_StopGrabbing(handle_);MV_CC_CloseDevice(handle_);MV_CC_DestroyHandle(handle_);}}private:void*handle_=nullptr;std::thread grabThread_;std::atomic<bool>running_{true};FrameRateCounter fpsCounter_;};2. Basler pylon C++ SDK
// BaslerFPS.cpp#include<pylon/PylonIncludes.h>#include"FrameRateCounter.h"classBaslerCamera{public:voidOpenAndStart(){camera_=Pylon::CTlFactory::GetInstance().CreateFirstDevice();camera_->Open();// 注册图像回调camera_->RegisterConfiguration(newPylon::CSoftwareTriggerConfiguration,Pylon::RegistrationMode_ReplaceAll,Pylon::Cleanup_Delete);camera_->StartGrabbing(Pylon::GrabStrategy_LatestImageOnly);// 启动取图循环grabThread_=std::thread([this](){Pylon::CGrabResultPtr ptrGrabResult;while(running_){if(camera_->RetrieveResult(1000,ptrGrabResult,Pylon::TimeoutHandling_ThrowException)){if(ptrGrabResult->GrabSucceeded()){fpsCounter_.OnNewFrame();// 关键:通知帧率计数器// 处理图像...}ptrGrabResult.Release();}}});}doubleGetFPS(){returnfpsCounter_.GetFPS();}~BaslerCamera(){running_=false;if(grabThread_.joinable())grabThread_.join();if(camera_->IsGrabbing())camera_->StopGrabbing();if(camera_->IsOpen())camera_->Close();}private:Pylon::CInstantCamera*camera_=nullptr;std::thread grabThread_;std::atomic<bool>running_{true};FrameRateCounter fpsCounter_;};3. 堡盟(Baumer)BGAPI C++ SDK
// BaumerFPS.cpp#include<bgapi2_genicam/bgapi2_genicam.hpp>#include"FrameRateCounter.h"classBaumerCamera{public:voidOpenAndStart(){BGAPI2::SystemList systemList;systemList.Refresh();autosystem=systemList.GetSystem("TFG");BGAPI2::InterfaceList interfaceList;system->GetInterfaces(interfaceList);interfaceList.Refresh();autointf=interfaceList.GetInterface(0);BGAPI2::DeviceList deviceList;intf->GetDevices(deviceList);deviceList.Refresh();device_=deviceList.GetDevice(0);device_->Open();dataStream_=device_->GetDataStream(0);dataStream_->Open();dataStream_->StartAcquisition();// 取图线程grabThread_=std::thread([this](){while(running_){autobuffer=dataStream_->GetBuffer(100);// 100ms timeoutif(buffer!=nullptr){fpsCounter_.OnNewFrame();// 关键:通知帧率计数器// 处理图像...dataStream_->QueueBuffer(buffer);}}});}doubleGetFPS(){returnfpsCounter_.GetFPS();}~BaumerCamera(){running_=false;if(grabThread_.joinable())grabThread_.join();if(dataStream_->IsOpen()){dataStream_->StopAcquisition();dataStream_->Close();}if(device_->IsOpen())device_->Close();}private:BGAPI2::Device*device_=nullptr;BGAPI2::DataStream*dataStream_=nullptr;std::thread grabThread_;std::atomic<bool>running_{true};FrameRateCounter fpsCounter_;};📈 四、获取理论最大帧率(C++)
有时也需要查询相机的理论极限帧率:
- 海康:
MV_CC_GetFloatValue(handle_, "AcquisitionFrameRate", &fValue) - Basler:
camera_->GetNodeMap()->GetNode("AcquisitionFrameRate")->GetValue() - 堡盟:
device_->GetRemoteNode("AcquisitionFrameRate")->GetDouble()
⚠️ 注意:理论帧率受曝光时间、带宽限制、ROI 等因素影响,通常需要先设置好其他参数再查询。
💬 结语
在 C++ 工业视觉应用中,精准的帧率监控是性能调优的基石。通过本文提供的跨品牌代码模板,你可以快速集成到自己的项目中,实时掌握系统的真实吞吐能力。
让每一微秒都高效,让每一帧都不被浪费。