如何開啟圖像采集線程與關閉該線程,步驟如下:
一、按下采集按鈕,開始建立一個圖像采集線程
// 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。
四、總結
我們可以以此類推,其他的應用場景。需要開啟線程,等待線程結束都可以使用這種方式。比如序列槽通信,網口通信等