vector of objects (insert and access)

Hi,

I’m headbanging with the question how to access the objects I have (hopefully) saved in a vector.
here’s the code

blob.h

  
#ifndef _BLOB  
#define _BLOB  
  
#include "ofMain.h"  
  
class blob{  
  
public:  
	blob(float x, float y, float theid);  
	  
	void update();  
	void draw();  
	  
	float x;  
	float y;  
	float theid;  
  
	blob();  
};  
  
#endif  

blob.cpp

  
#include "blob.h"  
  
blob::blob(float _x, float _y, float _theid){  
  
	x = _x;  
	y = _y;  
	theid = _theid;  
}  
  
void blob::update(){  
}  
  
void blob::draw(){  
	ofSetColor(100, 0, 0);  
	ofCircle(x, y, 10);  
}  

testApp.h

  
private:   
	blob ** myblob;   
	vector <blob> blobPerFrame;  
  

testApp.cpp
(and it’s all in the draw function:

  
if (contourFinder.blobs.size()>blobPerFrame.size()) {  
			blobPerFrame.insert(blobPerFrame.begin(),blob(blobX[0],blobY[0],i));  
		}  

this is supposed to insert a new blob into the array list… but I’m not sure if it really does… I mean I was thinking it should somehow be called “myblob” instead of “blob” but that gives me other errors… that’s why I really don’t know…

  
for (int i=0; i<blobPerFrame.size(); i++) {  
		myblob[i]->draw();  
	}  

and this should draw the blobs, but it doesn’t (error: bad memory access). I think I’m completely mixed up and I couldn’t find what I was needed looking in the forum.
Maybe someone can help?
thanks in advance!
Suse

  
  
if (contourFinder.blobs.size()>blobPerFrame.size()) {    
            blobPerFrame.push_back( blob(blobX[0],blobY[0],i) );    
        }  
  

I always use push_back()

  
  
for (int i=0; i<blobPerFrame.size(); i++) {    
        blobPerFrame[i].draw();    
    }    
  

I’m not one to use pointers if I can help it, so I access the element directly from the as if it were just a static array of objects.

I hope this helps.

thanks!
I still don’t get the difference between ** and *… I mean in the actual use… but it’s fine, as long as it works…

and just to make it a bit more complicated:
I need to have the objects inside a vector that’s inside another vector (so it’s like two-dimensional vector)… but how to access it then? c++ forums say just by vector[m][n], but oF says “statement cannot resolve address of an overloaded function”
here’s the code again (no changes in the class):

testApp.h

  
blob * myblob;   
	vector <blob> blobPerFrame;  
	vector < vector <blob> >allFrames;  

testApp.cpp

  
for(int j=0; j<contourFinder.blobs.size();j++){  
			blobPerFrame.push_back(blob(blobX[0],blobY[0],i));  
		}  
		allFrames.push_back(blobPerFrame);  

and

  
for (int i=0; i<allFrames.size()-1; i++) {  
		for (int j=0; j<blobPerFrame.size()-1; j++) {  
			allFrames[i][j].draw;  
		}  
  

Vectors of vectors are fine, I use them all the time :slight_smile:

Is your problem perhaps this:

  
allFrames[i][j].draw;   

should be?

  
allFrames[i][j].draw();   

One crucial difference between ** and * is that you can occasionally have a good reason to use *, while in C++, with all the container classes that it provides (vector, list, deque, etc) there’s pretty much no reason to ever use **.

stupid me!!! (and I like your quote: better mistakes tomorrow)
anyways, I’m running from one error to the next one… now I get a bad memory access in the stl_vector.h -file (line: 478)

  
  
      reference  
      operator[](size_type%20__n)  
      { return *(this->_M_impl._M_start + __n); }  

(last line)

(it’s of_preRelease_v0062_osxSL_FAT; running on Mac OS 10.6.8)

I tried deleting some instances of the vector, because this starts to starts an infinite number of vectors, but it didn’t help

You’re probably trying to access a point in the vector that doesn’t store anything somehow. This:

  
for (int i=0; i<allFrames.size()-1; i++) {    
        for (int j=0; j<blobPerFrame.size()-1; j++) {    
            allFrames[i][j].draw;    
        }    

looks wrong, you want something more like:

  
for (int i=0; i<allFrames.size()-1; i++) {    
        for (int j=0; j<allFrames.at(i).size()-1; j++) {    
            allFrames[i][j].draw;    
        }    

but it could be something else causing it as well. The standard library errors are a bit vague.

oh man,
thanks for your patience!
I changed it the way you adviced, now getting the signal: “SIGABRT”… any ideas how I could get rid of this?
maybe I should just save the length of the second vector other way so I can access it anyways?

That’s sort of the all-purpose “something has gone really wrong error”, it could be anything. Try commenting out sections to see if you can isolate what’s causing it, is it in pushing things into the array? Drawing? Updating? Etc. You’d have to post up more of your code for me to be more helpful.

Ok, I’ll post the whole code then;
By uncommenting I found that it seems the error is caused by one or two lines, actually the ones we discussed earlier. I put a comment in front of that line… it’s in testApp.cpp

testApp.h

  
#ifndef _TEST_APP  
#define _TEST_APP  
  
  
#include "ofMain.h"  
#include "ofxDirList.h"  
#include "ofxOpenCv.h"  
#include <vector>  
  
#include "blob.h"  
  
#define NumberOfStoredPositions 1000  
  
class testApp : public ofBaseApp{  
  
	public:  
		void setup();  
		void update();  
		void draw();  
  
		void keyPressed  (int key);  
		void keyReleased(int key);  
		void mouseMoved(int x, int y );  
		void mouseDragged(int x, int y, int button);  
		void mousePressed(int x, int y, int button);  
		void mouseReleased(int x, int y, int button);  
		void windowResized(int w, int h);  
	  
  
	  
	//-----------------------------------------  
	// my variables  
	//-----------------------------------------  
	  
	  
	int w, h; //size of images  
	string filename; //for screenshots  
	  
	//---------- video player  
	ofVideoPlayer video;  
	ofVideoPlayer emptyvideo;  
	  
	ofTexture vidTexture; //current image  
	unsigned char * vidPixels; //current pixels  
	  
	ofTexture originalTexture; //original image  
	unsigned char * originalPixels; //original pixels  
	  
	//----------OpenCv  
	ofxCvColorImage  colorImage;  
	ofxCvColorImage	backgroundColorImage;  
	  
	ofxCvGrayscaleImage grayImage;  
	ofxCvGrayscaleImage grayBackground;  
	ofxCvGrayscaleImage grayDifference;  
	ofxCvContourFinder contourFinder;  
	  
	bool bLearnBackground;  
	bool blobInBlob;  
	  
	int threshold;  
  
private:   
	blob * myblob;   
	vector <blob> blobPerFrame;  
	vector < vector <blob> >allFrames;  
};  
  
#endif  
  

testApp.cpp

  
#include "testApp.h"  
  
  
//--------------------------------------------------------------  
void testApp::setup(){  
	ofBackground(100, 0, 0);  
	  
	//---------videoplayer  
	video.loadMovie("timelapse01.mov");  
	video.play();  
	  
	emptyvideo.loadMovie("timelapse01_empty.mov");  
	  
	//----------original image  
	originalTexture.allocate(video.width,video.height,GL_RGB);  
	originalPixels= new unsigned char [video.width*video.height*3];  
	  
	originalPixels=emptyvideo.getPixels();  
	  
	  
	w=video.width;  
	h=video.height;  
	  
	vidTexture.allocate(video.width,video.height,GL_RGB);  
	vidPixels=new unsigned char [video.width*video.height,GL_RGB];  
	  
	//---------------openCv  
	colorImage.allocate(w,h);  
	grayImage.allocate(w,h);  
	backgroundColorImage.allocate(w, h);  
	grayBackground.allocate(w,h);  
	grayDifference.allocate(w,h);  
	  
	bLearnBackground=true;  
	threshold=70;  
}  
  
//--------------------------------------------------------------  
void testApp::update(){  
	//-----  
	vidPixels=video.getPixels();  
	//-----  
	//1. color image  
	colorImage.setFromPixels(vidPixels,w,h);  
	//2. gray image  
	grayImage = colorImage;  
	//3. background  
	backgroundColorImage.setFromPixels(originalPixels,w,h);  
	grayBackground=backgroundColorImage;  
	//4. difference  
	grayDifference.absDiff(grayImage, grayBackground);  
	grayDifference.threshold(threshold);  
	grayDifference.blur(5);  
	  
	//5. contours, blobs  
	contourFinder.findContours(grayDifference, 20,grayDifference.width*grayDifference.height/3, 3, blobInBlob);  
	  
		  
}  
  
//--------------------------------------------------------------  
void testApp::draw(){  
	  
	colorImage.draw(0,0, w/2,h/2); //upper left  
	grayImage.draw(w/2,0, w/2,h/2); //upper middle  
	grayBackground.draw(0,h/2, w/2,h/2); //lower left  
	grayDifference.draw(w/2,h/2, w/2,h/2);//lower middle  
	contourFinder.draw(w,0,w/2,h/2); //upper right  
	  
	for (int i=0; i<contourFinder.blobs.size(); i++) {  
		ofPushMatrix();  
		ofTranslate(w, h/2);  
		float blobX[contourFinder.blobs.size()];  
		float blobY[contourFinder.blobs.size()];  
		blobX[i]= (contourFinder.blobs[i].centroid.x/colorImage.width)*w;   
		blobY[i]= contourFinder.blobs[i].centroid.y/colorImage.height*h;  
		ofScale(0.5, 0.5);  
		  
		ofBeginShape();  
		ofSetColor(255, 0, 0);  
		for (int j=0; j<contourFinder.blobs[i].nPts; j++)  
		{  
			ofVertex(contourFinder.blobs[i].pts[j].x/colorImage.width*w, contourFinder.blobs[i].pts[j].y/colorImage.height*h);  
		}  
		ofEndShape(true);  
		ofSetColor(200, 200, 200);  
		ofCircle(blobX[i], blobY[i], 10);  
		ofPopMatrix();  
		  
		//------------class  
		for(int j=0; j<contourFinder.blobs.size();j++){  
			blobPerFrame.push_back(blob(blobX[0],blobY[0],i));  
		}  
		  
	}  
	allFrames.push_back(blobPerFrame);  
	if (allFrames.size()>300) {  
		allFrames.erase(allFrames.begin(),allFrames.begin());  
	}  
	  
	//----------------drawing  
	ofPushMatrix();  
	ofSetColor(0,200,0,100);  
	ofScale(0.5,0.5);  
	for (int a=0; a<allFrames.size()-1; a++) {  
		//it seems the SIGTERM-error is caused by the following line  
		for (int b=0; b<allFrames.at(a).size()-1; b++) {  
			//maybe there is another error in here (or the drawing function?) > at least I'm getting another error if I uncomment this  
			allFrames[a]**.draw();  
		}  
	}  
	   
	ofPopMatrix();  
	ofSetColor(200, 200, 200);  
	  
}  
  
  
//--------------------------------------------------------------  
void testApp::keyPressed(int key){  
	if (key=='s') {  
		ofSaveScreen(filename);  
		filename= "screenshot_"+ofToString(ofGetYear())+"-"+ofToString(ofGetMonth())+"-"+ ofToString(ofGetDay())+"_"+ ofToString(ofGetHours())+":"+ofToString(ofGetMinutes())+":"+ofToString(ofGetSeconds())+".png";  
	}  
  
}  
  
//--------------------------------------------------------------  
void testApp::keyReleased(int key){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseMoved(int x, int y ){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseDragged(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mousePressed(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::mouseReleased(int x, int y, int button){  
  
}  
  
//--------------------------------------------------------------  
void testApp::windowResized(int w, int h){  
  
}  
  
  

[b]blob.h**

  
  
#ifndef _BLOB  
#define _BLOB  
  
#include "ofMain.h"  
  
class blob{  
  
public:  
	blob(float x, float y, float theid);  
	  
	void update();  
	void draw();  
	  
	float x;  
	float y;  
	float theid;  
	  
	blob();  
};  
  
#endif  

blob.cpp

  
#include "blob.h"  
  
blob::blob(float _x, float _y, float _theid){  
  
	x = _x;  
	y = _y;  
	theid = _theid;  
}  
  
void blob::update(){  
}  
  
void blob::draw(){  
	ofSetColor(100, 0, 0);  
	ofCircle(x, y, 10);  
}  

Have you tried it without the -1 in size()-1 ?

thanks!
I was so used that you actually need to -1 if you deal with sizes that I didn’t think of that.
it doesn’t give an error, although it doesn’t do what it is expected to do either :wink:
I’ll post when I get to look at it closer again!

it looks like I still have something I don’t understand going on in the drawing part of the objects.
I checked there are actually values stored in the objects, and also that they are added properly to the vectors. that seems to work fine.
here is the whole void draw

  
colorImage.draw(0,0, w/2,h/2); //upper left  
	grayImage.draw(w/2,0, w/2,h/2); //upper middle  
	grayBackground.draw(0,h/2, w/2,h/2); //lower left  
	grayDifference.draw(w/2,h/2, w/2,h/2);//lower middle  
	contourFinder.draw(w,0,w/2,h/2); //upper right  
	  
	for (int i=0; i<contourFinder.blobs.size(); i++) {  
		ofPushMatrix();  
		ofTranslate(w, h/2);  
		float blobX[contourFinder.blobs.size()];  
		float blobY[contourFinder.blobs.size()];  
		blobX[i]= (contourFinder.blobs[i].centroid.x/colorImage.width)*w;   
		blobY[i]= contourFinder.blobs[i].centroid.y/colorImage.height*h;  
		ofScale(0.5, 0.5);  
		  
		ofBeginShape();  
		ofSetColor(255, 0, 0);  
		for (int j=0; j<contourFinder.blobs[i].nPts; j++)  
		{  
			ofVertex(contourFinder.blobs[i].pts[j].x/colorImage.width*w, contourFinder.blobs[i].pts[j].y/colorImage.height*h);  
		}  
		ofEndShape(true);  
		ofSetColor(200, 200, 200);  
		ofCircle(blobX[i], blobY[i], 10);  
		ofDrawBitmapString(ofToString(i), blobX[i]+3, blobY[i]);  
		ofPopMatrix();  
		ofDrawBitmapString(ofToString(contourFinder.blobs.size(),0), 10, 10);  
		//------------class  
		for(int j=0; j<contourFinder.blobs.size();j++){  
			blobPerFrame.push_back(blob(blobX[0],blobY[0],i));  
			//just checkin if I do it right  
			ofSetColor(100, 0, 0);  
			ofRect(w, 0, w+100, 50);  
			ofSetColor(200, 200, 200);  
			ofDrawBitmapString("added"+ofToString(i), w, 10+i*10);  
			ofDrawBitmapString("blobPerFrame.size "+ofToString(blobPerFrame.size(), 0), w, 40);  
		}  
		  
	}  
	allFrames.push_back(blobPerFrame);  
	  
	//clear content of the vector so it doesn't add up all the time  
	blobPerFrame.clear(); // I added this otherwise it always adds up the blobPerFrame values  
	  
	ofDrawBitmapString("pushed back frame", w+60, 10);  
	ofDrawBitmapString("allframes.size="+ofToString(allFrames.size(), 0), w+200, 10); //here it says 50 as it should  
	if (allFrames.size()==50) {  
		allFrames.erase(allFrames.begin(),allFrames.begin()+1);  
		ofDrawBitmapString("erased Frame", w+400, 10);  
	}  
	  
	//----------------drawing  
	ofPushMatrix();  
	//ofSetColor(0,200,0,2);  
	//ofScale(0.5,0.5);  
	for (int a=0; a<allFrames.size(); a++) {  
		ofSetColor(100, 0, 0);  
		ofRect(w, 40, w+25, 100);  
		ofSetColor(200, 200, 200);  
		ofDrawBitmapString("allframes no"+ofToString(a,0), w, 50);  
		ofDrawBitmapString("allFrames.size:"+ofToString(allFrames.size(), 0), w, 60); //here it's just 49 + "a" only goes up to 48 which is fine, but why is allFrames.size() different in here???  
		  
		for (int b=0; b<allFrames.at(a).size(); b++) {   
			//ofScale(0.5,0.5);  
			ofSetColor(100, 0, 0);  
			ofRect(w, 90, 1.5*w, 200);  
			ofSetColor(200, 200, 200);  
			ofDrawBitmapString("blobPerFrame at "+ofToString(a, 0)+"draws at position "+ofToString(b, 0), w, 100);  
			ofDrawBitmapString("allFrames.at a.size:"+ofToString(allFrames.at(a).size(), 0), w, 110);  
			allFrames[a][b].draw();  
		}  
	}  
	   
	ofPopMatrix();  
	ofSetColor(200, 200, 200);  

what’s happening is that the function allFrames.size() gives me 2 different values (50 or 49) in different parts of the code although I don’t add or delete anything from it in between.
and allthough the values of b are often more then 1, it only draws me 1 circle(that’s the object-class)…
where could the mistake be? when I store the values of the objects? (but I cann’t find it there either…)

dude me! (again)
it seems you always understand after you posted in here…
had a mistake in the storing:
instead of

  
blobPerFrame.push_back(blob(blobX[0],blobY[0],i));  

it has to be

  
blobPerFrame.push_back(blob(blobX[j],blobY[j],i));  

it seems to work better now…