Click here to Skip to main content
15,890,882 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hello everybody,

I'm working in an image processing project. I must use thread because of application's speed. In first thread, I take my image and in second thread I process my image. These must be simultaneously. I think I must use multiple buffer. But how??? Do you have any idea or sample code to do it.

Best regards...
Posted
Comments
mbue 25-Sep-11 8:16am    
Not neccessarily, this depend on the things you want to do. For a single operation (i.e. greyscale) you can break the bitmap in some parts and process every part by a single thread.
i.e. your bitmap has 800 lines and every of your 8 threads processing 100 lines and put the 100 lines to the output bitmap.
Regards.
Richard MacCutchan 25-Sep-11 8:24am    
Sorry posted in wrong place.
Richard MacCutchan 25-Sep-11 8:25am    
Why does this need multi-threading, can you actually process the image before you finish taking it?
AhmetBurak 25-Sep-11 8:30am    
Because of speed. My camera take 50 fps and my aplication must be 50 fps, too. While camera is taking image, I must process my old image.
Sergey Alexandrovich Kryukov 25-Sep-11 15:15pm    
Do you realize that one thread should wait for another one anyway? Still you can improve performance the way mbue suggested.
--SA

I have measured.
C++
  typedef struct
  {
    BITMAPINFO*      pBmp;
    unsigned char*  lpBytes;
    unsigned int    cbBytes;
    unsigned int    firstline;
    unsigned int    linecount;
  } PROCESS_STRUCT;
  static unsigned long FAR PASCAL  __process24(void* p)
  {
    PROCESS_STRUCT*  ps = (PROCESS_STRUCT*)p;
    unsigned int    bpl = ((ps->pBmp->bmiHeader.biWidth*3)+3) & ~3;
    unsigned char*  lpl = ps->lpBytes + bpl * ps->firstline;
    unsigned char*  lpp;
    unsigned int    x,y;
    for(y=0;y<ps->linecount;y++)
    {
      lpp = lpl;
      for(x=0;(int)x<ps->pBmp->bmiHeader.biWidth;x++,lpp+=3)
      {
        lpp[0] = 
        lpp[1] = 
        lpp[2] = (unsigned char)(((unsigned int)lpp[0]+(unsigned int)lpp[1]+(unsigned int)lpp[2])/3);
      }
      lpl += bpl;
    }
    return 0;
  }
  static unsigned long FAR PASCAL  __process32(void* p)
  {
    PROCESS_STRUCT*  ps = (PROCESS_STRUCT*)p;
    unsigned int    bpl = ps->pBmp->bmiHeader.biWidth * 4;
    unsigned char*  lpl = ps->lpBytes + bpl * ps->firstline;
    unsigned char*  lpp;
    unsigned int    x,y;
    for(y=0;y<ps->linecount;y++)
    {
      lpp = lpl;
      for(x=0;(int)x<ps->pBmp->bmiHeader.biWidth;x++,lpp+=4)
      {
        lpp[0] = 
        lpp[1] = 
        lpp[2] = (unsigned char)(((unsigned int)lpp[0]+(unsigned int)lpp[1]+(unsigned int)lpp[2])/3);
      }
      lpl += bpl;
    }
    return 0;
  }

  static void __ProcessBitmap(const unsigned int nthreads,BITMAPINFO* pBmp,unsigned char* lpBytes,unsigned int cbBytes)
  {
    HANDLE              ah[32]; // number of processors == best time
    unsigned int        ih;
    unsigned long        tid;
    PROCESS_STRUCT      pst[32];
    unsigned int        lpp = pBmp->bmiHeader.biHeight / nthreads;

    ASSERT((0<nthreads) && ((sizeof(ah)/sizeof(ah[0]))>=nthreads));

    switch(pBmp->bmiHeader.biBitCount)
    {
      case 24:
        pst[0].firstline = 0;
        for(ih=0;ih<nthreads;ih++)
        {
          if((1+ih)==nthreads) pst[ih].linecount = pBmp->bmiHeader.biHeight-pst[ih].firstline;
          else pst[ih].linecount = min(lpp,pBmp->bmiHeader.biHeight-pst[ih].firstline);
          pst[ih].pBmp    = pBmp;
          pst[ih].lpBytes = lpBytes;
          pst[ih].cbBytes = cbBytes;
          ah[ih] = CreateThread(0,0,__process24,&pst[ih],0,&tid);
          if((1+ih)<nthreads) pst[ih+1].firstline = pst[ih].firstline + pst[ih].linecount;
        }
        WaitForMultipleObjects(ih,ah,1,INFINITE);
      break;
      case 32:
        pst[0].firstline = 0;
        for(ih=0;ih<nthreads;ih++)
        {
          if((1+ih)==nthreads) pst[ih].linecount = pBmp->bmiHeader.biHeight-pst[ih].firstline;
          else pst[ih].linecount = min(lpp,pBmp->bmiHeader.biHeight-pst[ih].firstline);
          pst[ih].pBmp    = pBmp;
          pst[ih].lpBytes = lpBytes;
          pst[ih].cbBytes = cbBytes;
          ah[ih] = CreateThread(0,0,__process32,&pst[ih],0,&tid);
          if((1+ih)<nthreads) pst[ih+1].firstline = pst[ih].firstline + pst[ih].linecount;
        }
        WaitForMultipleObjects(ih,ah,1,INFINITE);
      break;
    }
  }


void ProcessImage(BITMAPINFO* pBmp,unsigned char* lpBytes,unsigned int cbBytes)
{
  // start time measurement
  __ProcessBitmap(_max_threads,pBmp,lpBytes,cbBytes);
  // stop time measurement and add to statistics
}

the results for _max_threads:
C++
  // 1 == 2.64 ms
  // 2 == 1.80 ms
  // 3 == 2.18 ms
  // 4 == 2.00 ms

bitmap is 32 bit 640x480 from the webcam.
on i3 that has 2 physical cores.
Regards.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 25-Sep-11 15:17pm    
Good little research; however, the problem is: we don't know what kind of processing OP will need, and the solution heavily depends on that. You provided the idea, anyway; my 5.
--SA
Albert Holguin 25-Sep-11 16:44pm    
You're right on about that...
mbue 25-Sep-11 16:46pm    
Indeed that was my first comment statement.
Ragards.
Simple way of doing it... allocate memory on the heap every time there's a new image and pass a pointer to the processing thread. The processing thread then needs to deallocate the memory after its done with it. You can probably have the common access point be a linked list of image pointers and just have the access control be a mutex or something similar.
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900