views:

91

answers:

1

Hi, I am trying to implement the codebook foreground detection algorithm outlined here in the book Learning OpenCV.

The algorithm only describes a codebook based approach for each pixel of the picture. So I took the simplest approach that came to mind - to have a array of codebooks, one for each pixel, much like the matrix structure underlying IplImage. The length of the array is equal to the number of pixels in the image.

I wrote the following two loops to learn the background and segment the foreground. It uses my limited understanding of the matrix structure inside the src image, and uses pointer arithmetic to traverse the pixels.

  void foreground(IplImage* src, IplImage* dst, codeBook* c, int* minMod, int* maxMod){

 int height = src->height;
 int width = src->width;

 uchar* srcCurrent = (uchar*) src->imageData;
 uchar* srcRowHead = srcCurrent;
 int srcChannels = src->nChannels;
 int srcRowWidth = src->widthStep;

 uchar* dstCurrent = (uchar*) dst->imageData;
 uchar* dstRowHead = dstCurrent;
 // dst has 1 channel
 int dstRowWidth = dst->widthStep;

 for(int row = 0; row < height; row++){
  for(int column = 0; column < width; column++){
   (*dstCurrent) = find_foreground(srcCurrent, (*c), srcChannels, minMod, maxMod);
   dstCurrent++;
   c++;
   srcCurrent += srcChannels;
  }
  srcCurrent = srcRowHead + srcRowWidth;
  srcRowHead = srcCurrent;
  dstCurrent = dstRowHead + dstRowWidth;
  dstRowHead = dstCurrent;
 }
}

void background(IplImage* src, codeBook* c, unsigned* learnBounds){

 int height = src->height;
 int width = src->width;

 uchar* srcCurrent = (uchar*) src->imageData;
 uchar* srcRowHead = srcCurrent;
 int srcChannels = src->nChannels;
 int srcRowWidth = src->widthStep;

 for(int row = 0; row < height; row++){
  for(int column = 0; column < width; column++){
   update_codebook(srcCurrent, c[row*column], learnBounds, srcChannels);
   srcCurrent += srcChannels;
  }
  srcCurrent = srcRowHead + srcRowWidth;
  srcRowHead = srcCurrent;
 }
}

The program works, but is very sluggish. Is there something obvious that is slowing it down? Or is it an inherent problem in the simple implementation? Is there anything I can do to speed it up? Each code book is sorted in no specific order, so it does take linear time to process each pixel. So double the background samples, and the program runs slower by 2 for each pixel, which is then magnified by the number of pixels. But as the implementation stands, I don't see any clear, logical way to sort the code element entries.

I am aware that there is an example implementation of the same algorithm in the opencv samples. However, that structure seems to be much more complex. I am looking more to understand the reasoning behind this method, I am aware that I can just modify the sample for real life applications.

Thanks

A: 

Operating on every pixel in an image is going to be slow, regardless of how you implement it.

Alexander Rafferty
But is there any significant things about this implementation that is slowing it down? The sample code in the examples section runs much faster but implements essentially the same idea i think...
No. Anything outside of your loops are negligible for speed optimization.
Alexander Rafferty