天天看點

相機開啟圖像采集與結束圖像采集的步驟

如何開啟圖像采集線程與關閉該線程,步驟如下:

一、按下采集按鈕,開始建立一個圖像采集線程

// 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。

四、總結

我們可以以此類推,其他的應用場景。需要開啟線程,等待線程結束都可以使用這種方式。比如序列槽通信,網口通信等

繼續閱讀