array being filled with same pointer

First, and foremost, a warning: I am a c# developer, so c++ is a whole different beast for me...

I am using OpenCV to grab images from a webcam, and I am trying to keep a running history in an array. I can't find a reason for this stepping though, but pretty quickly my history array craps out and the only symptom I can find is the pointers are all the same value.

My idea is first to fill the array, and once it is full to throw away the 0 index image, and shift them all down one, filling the last element with the current image.

My code is:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
IplImage*	_imgHistory[MAX_HISTORY];

bool Background::setHistory(IplImage* inputImg) {
//Add to the history array
if (!_imgHistory[MAX_HISTORY-1]) {
  // History is not yet full, so find the first empty spot
  for (int i=0;i<MAX_HISTORY;i++) {
    if (!_imgHistory[i]) {
      _imgHistory[i] = cvCloneImage(inputImg);
      printf("Frame: %d\n", i);
      return false;  // no point in continuing since history is still filling
    }
  }
}

//Make room for the next frame
cvReleaseImage(&_imgHistory[0]);
for (int i=0;i<MAX_HISTORY-2;i++)
  _imgHistory[i] = _imgHistory[i+1];
_imgHistory[MAX_HISTORY-1] = cvCloneImage(inputImg);
return true;
}
Last edited on
First thing is to replace that array with a deque or boost::circular_array.
Raw arrays are rarely used in C++ and it would be madness to implement basic functionality like removal of an element manually when there is no need.

Edit: cvReleaseImage(&_imgHistory[0]); doesn't look correct either. Surely you want to pass the pointer to the image and not a pointer to the pointer to the image?
Last edited on
Thanks Athar, I'll look at those options

As far as cvReleaseImage, There is certainly a problem somewhere, because I am quickly filling my memory, and something is not being released. I believe what I have is right, as the declaration is:

1
2
/* Releases IPL image header and data */
CVAPI(void)  cvReleaseImage( IplImage** image );
In that case the cvReleaseImage call is probably correct, however your loop limit should be MAX_HISTORY-1, not MAX_HISTORY-2.
Last edited on
The MAX_HISTORY - 2 is used since the loop references i+1

I converted to deque, but now I am getting errors from opencv, I think because the type inside the deque is showing as IplImage*&

UpdateImage(IplImage*) adds the image to history (via setHistory), then uses the history to try to determine what is static background and what is foreground...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
deque<IplImage*> 	_imgHistory;

void Background::UpdateImage(IplImage* inputImg) {
	if (!this->setHistory(inputImg))
		return;

	IplImage* diff = cvCreateImage(cvGetSize(inputImg), inputImg->depth, inputImg->nChannels);

        // Error happens in here, _imgHistory.front() and back() returns IplImage*&
	cvAbsDiff(_imgHistory.front(), _imgHistory.back(), diff);
	cvThreshold(diff, diff, 30, 255, CV_THRESH_BINARY);
	if (_currBackground)
		cvReleaseImage(&_currBackground);
	_currBackground = diff;

	cvReleaseImage(&inputImg);
}

bool Background::setHistory(IplImage* inputImg) {
	_counter++;
	printf("Count: %d\n", _counter);
	//Add to the history array
	if (_imgHistory.size()<MAX_HISTORY) {
		// History is not yet full, so find the first empty spot
		_imgHistory.push_back(cvCloneImage(inputImg));
		printf("Frame: %d\n", _imgHistory.size());
		return _imgHistory.size() == MAX_HISTORY;
	}

	//Make room for the next frame
	cvReleaseImage(&_imgHistory.front());
	_imgHistory.pop_front();
	_imgHistory.push_back(cvCloneImage(inputImg));
	return true;
}

Last edited on
The MAX_HISTORY - 2 is used since the loop references i+1

Yes, but it still should have been MAX_HISTORY-1. With the condition i<MAX_HISTORY-2, i will go up to MAX_HISTORY-3, so history[MAX_HISTORY-2] would be assigned to history[MAX_HISTORY-3] in the last iteration. The last element remains untouched and therefore the second to last element is being replicated all over the array which results in newer frames not being freed, as they never get to wander to the front of the array.

The line cvAbsDiff(_imgHistory.front(), _imgHistory.back(), diff); should be fine, though (it should compile, at least). IplImage*& is a reference to a pointer and since references are aliases, you can use it everywhere where a pointer to IplImage is expected. If this line still produces an error, you should post the exact error messages.
Topic archived. No new replies allowed.