圖像採集及處理多線程編程

本文介紹MFC中圖像採集及圖像處理的多線程編方法。創建了三個線程,分別爲圖像採集、圖像處理及圖像顯示線程。線程之間的共享數據有保存的圖像鏈表和圖像處理結果存儲結構。

圖像鏈表:list<Hobject> imgList;
存儲結構體:
struct ResultContainer
{
Hobject result_img;
HTuple time_needed;
HTuple result_handle;
HTuple result_data;
};

創建4個事件保證線程同步性

HANDLE  fgStopEvent;
HANDLE  newImageEvent;
HANDLE  newResultEvent;
HANDLE  containerIsFreeEvent;

使用2個關鍵段保證共享數據使用的互斥性

CRITICAL_SECTION    newImageMutex;
CRITICAL_SECTION    resultDataMutex;

同時在頭文件中加入私有成員變量:

HANDLE             dispThrHandle;        //Win32線程句柄        
unsigned int       dispThreadId;         //Win32線程標識符  
HANDLE             ipThrHandle;          //Win32線程句柄
unsigned int       ipThreadId;           //Win32線程標識符
HANDLE             fgThrHandle;          //Win32線程句柄
unsigned int       fgThreadId;           //Win32線程標識符
  1. 在初始化中進行關鍵段的初始化,創建線程等其他數據初始化過程:
    關鍵段初始化:
  InitializeCriticalSection(&newImageMutex);    
  InitializeCriticalSection(&resultDataMutex);

設置事件句柄以同步線程:

fgStopEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
newImageEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
newResultEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
containerIsFreeEvent =CreateEvent(NULL,FALSE,TRUE,NULL);

初始化共享數據:

resultData.time_needed = NULL; 
resultData.result_img = NULL;
resultData.result_handle = NULL;
resultData.result_data = NULL;

其他:

ResetEvent(fgStopEvent);    //設置fgStopEvent爲無信號狀態
InitialGrabOfImage();       //圖像採集初始化
  1. 設置一個啓動按鈕,開啓線程,線程開啓函數如下:
void CMultiThreading::StartThreads()
{
  //所有事件設置爲初始狀態
  ResetEvent(fgStopEvent);
  ResetEvent(newImageEvent);
  ResetEvent(newResultEvent);
  SetEvent(containerIsFreeEvent);

  imgList.clear();

// 開啓線程 
  dispThrHandle = (HANDLE)_beginthreadex(NULL0, 
                (unsigned (__stdcall *)(void*))&DISPRun, 
                 this,                  
                 0,                 
                 &dispThreadId);            

  ipThrHandle = (HANDLE)_beginthreadex(NULL, 0,                 
                (unsigned (__stdcall *)(void*))&IPRun,  
                 this,                  
                 0,                 
                 &ipThreadId);              

  fgThrHandle = (HANDLE)_beginthreadex(NULL, 0,                 
              (unsigned (__stdcall *)(void*))&ImgAcqRun,    
              this,                 
               0,                   
              &fgThreadId);
}
  1. 設置一個停止按鈕,停止所有線程,只需將停止事件設置爲有信號狀態:
SetEvent(fgStopEvent); 
  1. 圖像採集線程:
void ImgAcqRun(void *pars)
{
  HTuple      sequenceName;
  Hobject     grabbedImage;
  Hlong       FGHandle;

  CMultiThreadingDlg *MultiThrDlg = (CMultiThreadingDlg*) pars;

  // ---------------------  INIT  ----------------------
  sequenceName = "datacode/ecc200/ecc200.seq";
  open_framegrabber("File",1,1,0,0,0,0,"default",-1,
  "default",-1,"default",sequenceName,
  "default",-1,-1,&FGHandle);


  // -----------------  WAIT FOR EVENTS  ---------------
  while (WAIT_OBJECT_0 != WaitForSingleObject((MultiThrDlg->fgStopEvent),0))    //Stop按鈕沒有觸發
  {

    grab_image_async(&grabbedImage,FGHandle,-1);        
    EnterCriticalSection(&MultiThrDlg->newImageMutex);        // CriticalSect關鍵段
    if((MultiThrDlg->imgList).size()<MAX_BUFFERS)                     
    {                                                                                       
      (MultiThrDlg->imgList).push_back(grabbedImage);              
    }                                                                                      
    LeaveCriticalSection(&MultiThrDlg->newImageMutex);        // CriticalSect

    SetEvent(MultiThrDlg->newImageEvent);   //觸發事件
  }

  // -----------------  RESET/CLOSE ALL HANDLES  -------
  ResetEvent( MultiThrDlg->newImageEvent);
  close_framegrabber(FGHandle);

  return;
}
  1. 圖像處理線程:
void IPRun(void *pars)
{

  HTuple      T1,resultHandles,T2;
  Hobject     result_data, image;
  CString     sVal;
  HANDLE      eventHandle[2];

  struct ResultContainer ResultDataIP;
  CMultiThreadingDlg *MultiThrDlg = (CMultiThreadingDlg*) pars;     

  // --------------------  INIT ------------------------
  //圖像初始化操作

  // -----------------  WAIT FOR EVENTS  ---------------
  eventHandle[0] = (*MultiThrDlg).newImageEvent; 
  eventHandle[1] = (*MultiThrDlg).fgStopEvent;  

  while (WAIT_OBJECT_0 == WaitForMultipleObjects(2,eventHandle,
                                                 FALSE,INFINITE))
  {
    EnterCriticalSection(&MultiThrDlg->newImageMutex);      // CriticalSect
    image =  (MultiThrDlg->imgList).front();    
    MultiThrDlg->imgList.pop_front();   
    LeaveCriticalSection(&MultiThrDlg->newImageMutex);        // CriticalSect

    count_seconds(&T1);
    //圖像處理過程
    count_seconds(&T2);

    ResultDataIP.time_needed   = 1000*(T2[0].D() - T1[0].D());
    ResultDataIP.result_img    = image;  
    ResultDataIP.result_handle = resultHandles;
    ResultDataIP.result_data   = result_data;   

    WaitForSingleObject(MultiThrDlg->containerIsFreeEvent,INFINITE);
    EnterCriticalSection(&MultiThrDlg->resultDataMutex); 
// CriticalSect     
    MultiThrDlg->resultData = ResultDataIP;   
// CriticalSect                
    LeaveCriticalSection(&MultiThrDlg->resultDataMutex);     

    ResetEvent(MultiThrDlg->containerIsFreeEvent);
    SetEvent( MultiThrDlg->newResultEvent); 
  }

  // -----------------  RESET/CLOSE ALL HANDLES  -------
  ResetEvent(MultiThrDlg->newResultEvent);

  return;
}
  1. 顯示線程:
void DISPRun(void *pars)
{

  HTuple      time,resultHandles,i;
  Hobject     result_data, image;
  CString     sVal;
  Hlong       wWindowID;
  CRect       rect; 
  HANDLE      eventHandle[2];

  struct ResultContainer rData;
  CMultiThreadingDlg *MultiThrDlg = (CMultiThreadingDlg*) pars;
  wWindowID = (Hlong)MultiThrDlg->ipWinStatic.m_hWnd;
  MultiThrDlg->ipWinStatic.GetClientRect(&rect);


  // --------------------  INIT  -----------------------

  set_check("~father");
     open_window(0,0,rect.Width(),rect.Height(),wWindowID,
    "visible","", &(MultiThrDlg->windowID));
  set_check("father");

  set_window_attr("border_width",0);
  set_part(MultiThrDlg->windowID,0,0,MultiThrDlg->height-1,
           MultiThrDlg->width-1);
  set_color((MultiThrDlg->windowID),"green");
  set_line_width(MultiThrDlg->windowID,3);


  eventHandle[0] = ((*MultiThrDlg).newResultEvent); 
  eventHandle[1] = ((*MultiThrDlg)).fgStopEvent;  


  // -----------------  WAIT FOR EVENTS  ---------------
  while (WAIT_OBJECT_0 == WaitForMultipleObjects(2,eventHandle,
                                                 FALSE,INFINITE))
  {   
    EnterCriticalSection(&MultiThrDlg->resultDataMutex);      // CriticalSect
    rData = MultiThrDlg->resultData;                          // CriticalSect
    LeaveCriticalSection(&MultiThrDlg->resultDataMutex);      
    SetEvent(MultiThrDlg->containerIsFreeEvent);                 

    time               = rData.time_needed;
    image              = rData.result_img;  
    resultHandles      = rData.result_handle;
    result_data         = rData.result_data;    

    disp_obj(image,HTuple(MultiThrDlg->windowID));

    sVal.Format("%4.2f",time[0].D());
    (MultiThrDlg->ipProcTime).SetWindowText(sVal + " ms");

    disp_obj(symbolXLDs,HTuple(MultiThrDlg->windowID));

    for (i=0; i<=(resultHandles.Num())-1; i+=1)
    {
      (MultiThrDlg->ipImgLabel).SetWindowText(decodedDataStrings[i]);
    }  
  }

  // -----------------  RESET/CLOSE  ALL HANDLES  ------
  close_window(MultiThrDlg->windowID);
  SetEvent(MultiThrDlg->containerIsFreeEvent);
  MultiThrDlg->ipProcTime.SetWindowText("");

  return;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章