项目场景:
Baumer工业相机堡盟相机传统开发包BGAPI SDK进行工业视觉软件整合时,常常需要将SDK中一些功能整合到图像处理软件中,方便项目的推进使用;
注意:本文是基于Baumer的BGAPI SDK的基础上使用C++语言来实现相机帧率和网口数据通量的实时显示。
问题描述
在项目的图像处理任务中,有时需要将相机的帧率实时显示在图像处理软件的界面上。
但是Baumer BGAPI SDK上没有直接显示帧率的方法函数,这就需要小伙伴们结合SDK自己去写一个了
实现方法步骤1:确认帧率信息
基本上所有的相机图像数据都有一个FrameID,从开启采集后不断增加,一般情况下都是根据FrameID来计算当前相机的实时帧率。
首先,FrameID一般出现在相机图像的回调函数里,先定义全局变量FrameID去获取相机的FrameID。
FrameID在回调函数的代码如下所示
void BGAPI2CALL BufferHandler( void * callBackOwner, Buffer * pBufferFilled ) { CGigeDemoDlg* pDlg = (CGigeDemoDlg*)callBackOwner; unsigned char* imagebuffer = NULL; USES_CONVERSION; try { if(pBufferFilled == NULL) { } else if(pBufferFilled->GetIsIncomplete() == true) { // queue buffer again pBufferFilled->QueueBuffer(); } else { pDlg->FrameID= pBufferFilled->GetFrameID(); //获取当前图像FrameID显示帧率 } } catch (BGAPI2::Exceptions::IException& ex) { CString str; str.Format(_T("ExceptionType:%s! ErrorDescription:%s in function:%s"),ex.GetType(),ex.GetErrorDescription(),ex.GetFunctionName()); }
实现方法步骤2:定义显示线程
2、在头文件里定义一个线程去显示对应帧率的变化。
static UINT ShowFrame_hThread1(LPVOID pParam);//该线程的调用函数 void SetShowFrame();//在这个函数中编写该线程需要完成的任务
实现方法步骤3:实现线程方法
3、实现定义的线程方法,通过每秒的计算方式实时计算出相机的图像采集速度帧率
代码如下所示:
UINT CGigeDemoDlg::ShowFrame_hThread1(LPVOID pParam) { CGigeDemoDlg *dlg = (CGigeDemoDlg *)pParam; dlg->SetShowFrame(); return 0; } void CGigeDemoDlg::SetShowFrame() { try { while (m_bRun0) { if(FrameID>0) { double CurFrameID1 = FrameID; Sleep(1000); double CurFrameID2 = FrameID; double CalFrameID =(CurFrameID2-CurFrameID1)*1 ; //ShowFrame_hThread1->g_criticalsection.Lock(); //边界锁锁定 同步锁中间可添加需要保护的操作代码,如操作txt文档读、看、写时等。 //ShowFrame_hThread1->g_criticalsection.Unlock();//边界锁解除 if(m_pDataStream!=NULL) { try { BGAPI2::NodeMap* pDataStreamNodeList = m_pDataStream->GetNodeList(); if (m_pDataStream->GetTLType() == "GEV") { float m_CurStreamBitrateDouble = pDataStreamNodeList->GetNode("Bitrate")->GetDouble(); m_CurStreamBitrate.Format(_T("%.2f"),m_CurStreamBitrateDouble); GetDlgItem(IDC_STCURBITRATE)->SetWindowText(m_CurStreamBitrate+_T(" MBit/s")); //获取网口数据量并显示出来 } } catch (CMemoryException* e) {} } CString CurFameratestr; CurFameratestr.Format(_T("%.1f"),CalFrameID); //获取帧率并显示出来 m_Cursetframe = CurFameratestr; GetDlgItem(IDC_STCURFRAME)->SetWindowText(CurFameratestr); } } } catch (int e) { MessageBox(_T("Camera SetShowimage Error")); } }
实现方法步骤4:启动线程
4、在相机的启动时同时启动该线程
代码如下所示:
void CGigeDemoDlg::OnBnClickedBtnplay() { // TODO: 在此添加控件通知处理程序代码 USES_CONVERSION; if(m_pDevice != NULL) { try { m_pDevice->GetRemoteNode("TriggerMode")->SetString("Off"); //关闭触发模式,进入自由采集图片流模式 m_pDevice->GetRemoteNode("AcquisitionStart")->Execute(); #pragma region 线程显示帧率和网口数据通量(做参考) m_bRun0 = true; AfxBeginThread(ShowFrame_hThread1, (void*)this); #pragma endregion } catch (BGAPI2::Exceptions::IException& ex) { CString str1; str1.Format(_T("ExceptionType:%s! ErrorDescription:%s in function:%s"),ex.GetType(),ex.GetErrorDescription(),ex.GetFunctionName()); MessageBox(str1); } } }
实现方法步骤5:停止显示线程
5、如何关闭该线程,在相机关闭时需要正常关闭。
代码如下所示:
void CGigeDemoDlg::StopShowFrame_hThread1() { m_bRun0 = FALSE; //停止帧率和网口数据通量线程执行 WaitForSingleObject(ShowFrame_hThread1,200); //一直等待对应线程退出 Sleep(2000); //线程停止缓冲时间 /*DWORD exitcode2; GetExitCodeThread(ShowFrame_hThread1,&exitcode2); ExitThread(exitcode2); */ }
实现方法步骤6:帧率和网口数据通量显示
6、完成上面的操作后,在相机初始化并开启采图后就可以开启相机当前帧率和网口数据通量的显示