如何开启图像采集线程与关闭该线程,步骤如下:
一、按下采集按钮,开始创建一个图像采集线程
// ch:按下开始采集按钮 | en:Click Start button
void CBasicDemoDlg::OnBnClickedStartGrabbingButton()
{
if (FALSE == m_bOpenDevice || TRUE == m_bStartGrabbing || NULL == m_pcMyCamera)
{
return;
}
memset(&m_stImageInfo, 0, sizeof(MV_FRAME_OUT_INFO_EX));
m_bThreadState = TRUE;
unsigned int nThreadID = 0;
m_hGrabThread = (void*)_beginthreadex( NULL , 0 , GrabThread , this, 0 , &nThreadID );
if (NULL == m_hGrabThread)
{
m_bThreadState = FALSE;
ShowErrorMsg(TEXT("Create thread fail"), 0);
return;
}
int nRet = m_pcMyCamera->StartGrabbing();
if (MV_OK != nRet)
{
m_bThreadState = FALSE;
ShowErrorMsg(TEXT("Start grabbing fail"), nRet);
return;
}
m_bStartGrabbing = TRUE;
EnableControls(TRUE);
return;
}
在按下采集按钮事件中,使用_beginthreadex开启一个图像采集线程。
同时定义成员函数,保存线程的状态,线程的句柄
void* m_hGrabThread; // ch:取流线程句柄 | en:Grab thread handle
BOOL m_bThreadState; //线程状态
二、 采集过程
具体的线程执行函数
// ch:取流线程 | en:Grabbing thread
unsigned int __stdcall GrabThread(void* pUser)
{
if (NULL == pUser)
{
return -1;
}
CBasicDemoDlg* pCam = (CBasicDemoDlg*)pUser;//MFC窗体
pCam->GrabThreadProcess();
return 0;
}
具体的图像采集函数
int CBasicDemoDlg::GrabThreadProcess()
{
// ch:从相机中获取一帧图像大小 | en:Get size of one frame from camera
MVCC_INTVALUE_EX stIntValue = {0};
int nRet = m_pcMyCamera->GetIntValue("PayloadSize", &stIntValue);
if (nRet != MV_OK)
{
ShowErrorMsg(TEXT("failed in get PayloadSize"), nRet);
return nRet;
}
unsigned int nDataSize = (unsigned int)stIntValue.nCurValue;
if (NULL == m_pGrabBuf || nDataSize > m_nGrabBufSize)
{
if (m_pGrabBuf)
{
free(m_pGrabBuf);
m_pGrabBuf = NULL;
}
m_pGrabBuf = (unsigned char *)malloc(sizeof(unsigned char) * nDataSize);
if (m_pGrabBuf == NULL)
{
return 0;
}
m_nGrabBufSize = nDataSize;
}
MV_FRAME_OUT_INFO_EX stImageInfo = {0};
MV_DISPLAY_FRAME_INFO stDisplayInfo = {0};
while(m_bThreadState)
{
EnterCriticalSection(&m_hSaveImageMux);
nRet = m_pcMyCamera->GetOneFrameTimeout(m_pGrabBuf, m_nGrabBufSize, &stImageInfo, 1000);
if (nRet == MV_OK)
{
memcpy(&m_stImageInfo, &stImageInfo, sizeof(MV_FRAME_OUT_INFO_EX));
}
LeaveCriticalSection(&m_hSaveImageMux);
if (nRet == MV_OK)
{
if(RemoveCustomPixelFormats(stImageInfo.enPixelType))
{
continue;
}
stDisplayInfo.hWnd = m_hwndDisplay;
stDisplayInfo.pData = m_pGrabBuf;
stDisplayInfo.nDataLen = stImageInfo.nFrameLen;
stDisplayInfo.nWidth = stImageInfo.nWidth;
stDisplayInfo.nHeight = stImageInfo.nHeight;
stDisplayInfo.enPixelType = stImageInfo.enPixelType;
m_pcMyCamera->DisplayOneFrame(&stDisplayInfo);
}
else
{
if (MV_TRIGGER_MODE_ON == m_nTriggerMode)
{
Sleep(5);
}
}
}
return MV_OK;
}
我们可以看到,主要是通过一个While循环判断线程的状态,来不断的通过相机API图像信息stDisplayInfo
三、 结束采集
// ch:按下结束采集按钮 | en:Click Stop button
void CBasicDemoDlg::OnBnClickedStopGrabbingButton()
{
if (FALSE == m_bOpenDevice || FALSE == m_bStartGrabbing || NULL == m_pcMyCamera)
{
return;
}
m_bThreadState = FALSE;
if (m_hGrabThread)
{
WaitForSingleObject(m_hGrabThread, INFINITE);
CloseHandle(m_hGrabThread);
m_hGrabThread = NULL;
}
int nRet = m_pcMyCamera->StopGrabbing();
if (MV_OK != nRet)
{
ShowErrorMsg(TEXT("Stop grabbing fail"), nRet);
return;
}
m_bStartGrabbing = FALSE;
EnableControls(TRUE);
return;
}
我们可以看到,先将线程状态置为False,再等待线程执行完成,同时将线程句柄置为NULL,调用相机API关闭采集。
具体代码见海康的demo。
四、总结
我们可以以此类推,其他的应用场景。需要开启线程,等待线程结束都可以使用这种方式。比如串口通信,网口通信等