前言
这部分完成的功能是触发采图,所谓触发采图,基本的过程是在
先开启连续采图,然后,在某个触发信号到来的时候,读取其中的某一帧的信号,显示在主界面上
这个触发可以是软触发,也可以是硬件触发信号,看具体的需求,下面开讲大恒相机的触发采图。
正文
开启采图模式
首先,我们要让程序先开启采图模式,也就是处于回调抓图的模式,才能让相机在触发信号到来的信号进行抓图。我们这里使用的函数是
GrabThreadStart
:
GrabThreadStart
qint32 MDeviceDahengG3UC::GrabThreadStart()
{
qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV
if(m_bLoaded)
{
CGXFeatureControlPointer m_objFeatureControlPtr2 = m_objDevicePtr->GetRemoteFeatureControl();
if((!m_objDevicePtr.IsNull())&&(!m_objFeatureControlPtr2.IsNull()))
{
if(!m_objStreamPtr.IsNull())
{
m_objStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler,this);//
m_objStreamPtr->StartGrab();//startGrab
}
else
qDebug()<<"MDeviceDahengG3UC::GrabThreadStart m_objStreamPtr is null";
m_objFeatureControlPtr2->GetCommandFeature("AcquisitionStart")->Execute();
ret = RETURN_OK;
}
else
{
if(m_objDevicePtr.IsNull())
qDebug()<<"MDeviceDahengG3UC::GrabThreadStart m_objDevicePtr is null";
}
}
#endif
return ret;
}
下面进行解析:
- 这里面最重要的肯定是进行回调注册了,也就是这个函数:
m_objStreamPtr->RegisterCaptureCallback(m_pCaptureEventHandler,this);
这个函数在大恒相机的文档上有,我这里稍微解释一下,就是把这个
this
的指针传给
m_pCaptureEventHandler
这个对象,它这个注册函数的定义是这个:
//----------------------------------------------------------------------------------
virtual void RegisterCaptureCallback(ICaptureEventHandler* pEventHandler, void *pUserParam) = 0;
相当于,在这里注册了
pEventHandler
这个对象,并把
this
指针往下传,在你按下触发按钮的时候,就会执行这个对象里面的函数,也就是
ICaptureEventHandler
,我就顺势在这里给出这个函数的解析:
//回调处理类
class CSampleCaptureEventHandler : public ICaptureEventHandler
{
public:
void DoOnImageCaptured(CImageDataPointer& objImageDataPointer, void* pUserParam)
{
MDeviceDahengG3UC* pDev = static_cast<MDeviceDahengG3UC*>(pUserParam);
pDev->triggerEvent(objImageDataPointer);
}
};
注意,这个类是大恒相机给的,不是我自己创造的,所以,看文档就显得至关重要了,包括这个
RegisterCaptureCallback
这个函数也是文档里有的,我这里只是给你一个这种问题的解决方向。
当你触发信号到来后,就执行
DoOnImageCaptured
。
-
接着上面那个继续讲一下
triggerEvent
这个函数:
void MDeviceDahengG3UC::triggerEvent(CImageDataPointer objImageDataPointer)
{
#ifdef WIN32_DAHENG_GEV
if(m_bStopWork)
return;
if(m_fGrabCallbackEx)
{
MFrameInfo info;
info.nWidth = (qint32)objImageDataPointer->GetWidth();
info.nHeight = (qint32)objImageDataPointer->GetHeight();
info.nFramerLen = (qint32)objImageDataPointer->GetPayloadSize();
quint64 format = objImageDataPointer->GetPixelFormat();
info.cFormat = GetPixelFormat(format);
uchar *pbit = (uchar*)objImageDataPointer->GetBuffer();//Buffer
m_fGrabCallbackEx(m_pCallUser,pbit,&info);
}
#endif
}
这里的m_fGrabCallbackEx是从最上层往下传的一个回调函数,所以,你可以看到,我这里把所有有的东西都传给这个函数了,就是为了让这个函数带着这些东西回到最上层,从而把这个
pbit
地址里面的东西给我显示出来。我觉得如果你的程序,做成插件类型,并且要传到
MainWindow
的话,应该也是要使用这种方式。
- 注意最后要进行回调功能的关闭的话要进行Stop的操作,函数如下:
qint32 MDeviceDahengG3UC::GrabThreadStop()
{
qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV
//ɡ
CGXFeatureControlPointer m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
if(!m_objFeatureControlPtr.IsNull())
{
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
m_objStreamPtr->UnregisterCaptureCallback();
ret = RETURN_OK;
}
else
{
qDebug()<<"MDeviceDahengG3UC::GrabThreadStop m_objFeatureControlPtr is null";
}
#endif
return ret;
}
开启实时采图功能
接下来就该开启相机的连续采图功能,但并不显示在界面之上,也就是不去拿那些数据,这样就为后续的触发抓图做准备。这个函数与之前的实时采图所用的函数是一样的。这里使用的是
qint32 MDeviceDahengG3UC::AcquisitionStart()
{
qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV
if(m_bLoaded)
{
if(m_bStopWork)
{
m_objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
m_objImageProcessPtr = m_objDevicePtr->CreateImageProcessConfig();
bool m_bIsColorFilter = m_objFeatureControlPtr->IsImplemented("PixelColorFilter");
if(!m_objStreamPtr.IsNull())
{
qDebug()<<"MDeviceDahengG3UC::AcquisitionStart m_objStreamPtr";
//objStreamPtr->SetAcqusitionBufferNumber(10);//StartGrabòbufferЧ
m_objStreamPtr->StartGrab();
}
if(!m_objFeatureControlPtr.IsNull())
{
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")->Execute();
ret = RETURN_OK;
}
if(m_pConfigureObj->UpdateConfigureFromDevice())
m_pConfigureObj->SlotConfigChanged();
if(m_pConfigureObj->UpdateSimplyConfigureFromDevice())
m_pConfigureObj->SlotSimplyConfigChanged();
m_bStopWork =false;
}
}
#endif
return ret;
}
-
最主要的还是执行
Acquisition
这个命令:
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStart")-
-
我这里讲一下
UpdateConfigureFromDevice
这个函数的功能,从字面意思就可以知道,从
硬件中更新配置文件
,通过这样,在每次相机通道被创建的时候,就会从硬件中读取参数,这样的参数显示才是最新的。至于
simply
就不用管它来了。 -
这里还是稍微讲一下,上面有了
AcquisitionStart
,那肯定有
AcquisitionStop
。这里也贴出这个函数,还是比较简单的。
qint32 MDeviceDahengG3UC::AcquisitionStop()
{
qint32 ret = RETURN_FAIL;
#ifdef WIN32_DAHENG_GEV
if(m_bLoaded)
{
if(!m_bStopWork)
{
if((!m_objFeatureControlPtr.IsNull())&&(!m_objStreamPtr.IsNull()))
{
m_objFeatureControlPtr->GetCommandFeature("AcquisitionStop")->Execute();
m_objStreamPtr->StopGrab();
//
m_objStreamPtr->Close();
}
if(m_pConfigureObj->UpdateConfigureFromDevice())
m_pConfigureObj->SlotConfigChanged();
if(m_pConfigureObj->UpdateSimplyConfigureFromDevice())
m_pConfigureObj->SlotSimplyConfigChanged();
ret = RETURN_OK;
m_bStopWork = true;
}
}
#endif
return ret;
}
点击触发按钮
最后一步,当然是点击触发按钮,实现软触发了。这里也是比较简单,使用的是
TriggerSoftwareExecute
这个函数,下面直接给出:
qint32 MDeviceDahengG3UC::TriggerSoftwareExecute()
{
qint32 ret = RETURN_FAIL;
if(m_bLoaded)
{
if(!m_objDevicePtr.IsNull())
{
CGXFeatureControlPointer objFeatureControlPtr = m_objDevicePtr->GetRemoteFeatureControl();
if(!objFeatureControlPtr.IsNull())
{
CCommandFeaturePointer objCommandPtr = objFeatureControlPtr->GetCommandFeature("TriggerSoftware");
objCommandPtr->Execute();
ret = RETURN_OK;
}
}
}
return ret;
}
你直接软件触发的按钮和这个函数进行关联,执行
Execute
命令就可以了。
总结
我觉得对于回调采图的这部分,最难的地方应该还是在对回调函数的设置上面,对这个东西的理解,我之前一直也不是很理解,但后面弄的多了,也就有点理解了,你就找到那个回调函数,这个相机自带的回调函数就会在程序产生触发操作的时候调用里面的回调函数。希望你能成功解决这个问题。
这个部分还有另外两篇,这里给出地址,有需要的可以去看看:
若有错误,欢迎指出,感谢~