图像采集及处理多线程编程

本文介绍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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章