computerVision weirdness

After upgrading to OF 003 and running example computerVison code I noticed some weird behavior. I am not sure it has to do with 003 though. Anyway, here is the deal:

Attached is some code that graps a frame from the camera. It then assigns the pixels to a ofCvColorImage, and a ofCvGrayscaleImage. In the draw method both images and the videoGrapper are drawn.

The problem is that colorImg is drawn blank white. The cause for this is:
grayImage.setFromColorImage( colorImg );
Commenting out the latter results in the colorImg being draw correctly.

But it gets weirder. Even if I go to the implementation of setFromColorImage and comment everything out that is in there I get a blank colorImg. It seems that simply passing the colorImg to a method (of ofCvGrayscaleImage) that does not do anything changes it.

I have also found a solution to the problem but have no idea why it works. If I change from:
void ofCvGrayscaleImage::setFromColorImage(ofCvColorImage mom)
to:
void ofCvGrayscaleImage::setFromColorImage(ofCvColorImage& mom)
effectively passing colorImg as a reference.

Not sure what I am missing here but it puzzels me,
Anybody has an idea,

/stefan

  
  
#include "ofMain.h"  
#include "ofCvMain.h"  
  
class world : public ofSimpleApp {  
  public:  
	void setup();  
	void update();  
	void draw();  
	void keyPressed(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 cwidth;  
    int cheight;  
      
	ofVideoGrabber  vidGrabber;  
	ofCvColorImage  colorImg;  
    ofCvGrayscaleImage  grayImage;    
};  
  
  
  
  
void world::setup(){  
    cwidth = 320;  
    cheight = 240;  
	vidGrabber.setVerbose( true );  
	vidGrabber.initGrabber( cwidth,cheight );  
      
    colorImg.allocate( cwidth,cheight );  
	grayImage.allocate( cwidth,cheight );  
}  
  
  
  
void world::update(){  
	ofBackground(100,100,100);  
	vidGrabber.grabFrame();  
      
	if (vidGrabber.isFrameNew()){		  
		colorImg.setFromPixels(vidGrabber.getPixels(), cwidth,cheight );  
        grayImage.setFromColorImage( colorImg );  
	}  
}  
  
  
  
void world::draw(){  
      
    vidGrabber.draw( 20,20 );  
    colorImg.draw( 360,20 );  
    grayImage.draw( 700,20 );  
}  
  
void world::keyPressed( int key ) {}  
void world::mouseMoved( int x, int y ) {}  
void world::mouseDragged( int x, int y, int button ) {}  
void world::mousePressed( int x, int y, int button ) {}  
void world::mouseReleased() {}  
  
  
  
  
  
  
  
int main() {  
	ofSetupOpenGL( 1024, 768, OF_WINDOW );  
	world APP;  
	ofRunApp( &APP );  
}  
  

Ok, I have a guess what is happening:
When the image objects are passed in by value the copy constructor is called on them. Since it is not defined it uses the default one which does a shallow copy. This copy points to the same data sources and therefore affects the original image.

Other theories appreciated,

wow that was fast debugging, we spent a whole day on that in sweden and it was making us crazy. CJ has made the fix and we will upload it in the next major ofAddon iteration. you are absolutely right and it’s an issue of pass by copy vs. pass by reference… fix is coming up shortly, for now you can change all the ofCvGrayscaleImage mom, to ofCvGrayscaleImage &mom… sorry for any inconveniences –

take care
zach

hehe … good to know I wasn’t the only one puzzled by that.
Thanks for confirming,

I thought this thread solved a problem I was trying to fix, but mine is slightly different and I get the same problem.

I want to pass the colour image from the main app into my wrapper so that I have a copy. So far I do it like this (editted down a lot to make it easier to read):

  
  
// main app setup  
ofVideoGrabber  vidGrabber;  
ofCvColorImage  colorImg;   
  
// main app loop  
wrapper.updateImage(colorImg);  
  
// wrapper update function  
wrapperClass::updateImage( ofCvColorImage _image ){  
   localColorImage.setFromPixels(_image.getPixels(), sourceWidth, sourceHeight);  
}  
  

It seems as if actually the pixels are there (because my contour code still works), but when I draw the localColorImage it shows as a blank image. Could setFromPixels using getPixels clobber the image?

(this started with 0.03, was fine in 0.02)

Thanks

(sorry for thread hijak, hopefully they are very related)

yeah I think this is the same issue. pass by copy vs. copy be reference.

try this:

  
  
// main app loop  
wrapper.updateImage(colorImg);  // called the same way  
  
// wrapper update function  
wrapperClass::updateImage( ofCvColorImage &_image ){  // this is different (pass by ref)  
   localColorImage.setFromPixels(_image.getPixels(), sourceWidth, sourceHeight);  
}   
  

and I think it’ll work (you still use it the same way, but internally, the object is passed differently).

does that help ?

take care,
zach

Thanks. This now works.

I noticed something very odd. Even if the wrapper function was empty, the colour image in the main app still draws blank (even if you dont do anything to the colour image in the function)

wrapperClass::updateImage( ofCvColorImage &_image ){
// do nothing
}

It seems like quite a few things are now broken in this way

  1. warpIntoMe for grayscaleImage.

if you change it to this
warpIntoMe(ofCvGrayscaleImage &mom, ofPoint2f src[4], ofPoint2f dst[4])

the original grayscaleImage draws fine, but the new warpintome image doesn’t work anymore :frowning:

  1. floatImage addWeighted( grayImage, 0.3 )

grayImage no longer draws

chris,

it’s kind of hard to recreate the last two things you are mentioning. we’d really like to know the problems you are having.

we definitely want to suggest you wait for the next opencv addon coming shortly, where we have fixed all of the pass by reference issues.

can you please identify issues and post zips of the libs / app code that recreate them? should be as complete as possible (apps, libs, modified code, etc)…

also, better if your examples use images files or a small movie, since not always having access to a camera,

cheers
zach

  1. floatImage addWeighted( grayImage, 0.3 )

again, try defining it with pass by reference not pass by copy:

floatImage::addWeighted( ofCvGrayscaleImage & blah, float weight)

take care,
zach

I can’t post everything, as there is tonnes of unrelated code and its a client project (can post some cleaned up addons later). I haven’t modified the opencv addons, just the two suggestions above. For now I made a simple example to explain

http://www.chrisoshea.org/storage/ofw/p-…-e/main.cpp
http://www.chrisoshea.org/storage/ofw/p-…-/testApp.h
http://www.chrisoshea.org/storage/ofw/p-…-estApp.cpp

You should be able to compile it fine, it just needs openCV and fingers.mov in data folder.

The problems so far:

  1. grayImage warp into me breaks the original gray image
  2. floatImage::addWeighted breaks the passed in image
  3. graImage absoluteDiff breaks both images passed to it

when I say breaks it, I mean the original images dont display with draw()

I can’t see how it would be just a VC issue, but heres hoping. I fear I may have to go back to 0.02 for now as I’m on such a short time left for this project.

hi chris,

I will need to see the mofidied cv addon to help you –

if you haven’t modified it then it will break, because you need to make everything that is pass by copy, pass by reference.

what’s actually breaking, is that you are loosing the texture - so you can’t see anything anymore. data still exists, but it’s just not drawable.

happy to help but need a whole package to try it

zach

Here is my ofCV addon folder

http://www.chrisoshea.org/storage/ofw/p-…-OpenCV.zip

Not a lot should have changed

Many thanks

ok – i’ll check it

here is a modified opencv addon that should have solve everything:

openFrameworks.cc/files/cvModdedFor0.03.zip

can you please give it a try?

I think it should fix alot of the texture disapearing you have going on.

thanks
zach

Thanks for those. Comparing the files in ExamDiff there are lots of new things in this addon version.

When compiling I get these errors

1>ofCvColorImage.cpp
1>…\addons\cvModdedFor0.03\ofCvColorImage.cpp(65) : error C2027: use of undefined type ‘ofCvGrayscaleImage’
1> c:\openframeworks\v0.03\addons\cvmoddedfor0.03\ofCvColorImage.h(9) : see declaration of ‘ofCvGrayscaleImage’
1>…\addons\cvModdedFor0.03\ofCvColorImage.cpp(65) : error C2228: left of ‘.getCvImage’ must have class/struct/union
1>…\addons\cvModdedFor0.03\ofCvColorImage.cpp(70) : error C2027: use of undefined type ‘ofCvFloatImage’
1> c:\openframeworks\v0.03\addons\cvmoddedfor0.03\ofCvColorImage.h(10) : see declaration of ‘ofCvFloatImage’
1>…\addons\cvModdedFor0.03\ofCvColorImage.cpp(70) : error C2228: left of ‘.getCvImage’ must have class/struct/union

It seems it doesn’t like this at the top of ofCvColorImage.h maybe ?

  
  
class ofCvGrayscaleImage;  
class ofCvFloatImage;  
  

it’s the forward declaration

(have to add “class grayscaleImage” in the h file to avoid recursive linking)

change the top of ofCvColorImage from :

  
  
#include "ofCvColorImage.h"  
  

to

  
  
#include "ofCvColorImage.h"  
#include "ofCvGrayscaleImage.h"  
#include "ofCvFloatImage.h"  
  

that should work - these are changes CJ sent us, and we haven’t had a chance to test them yet, but believe they should fix everything — can you let me know if that fixes your problems?

-z

Hurray, that works and it fixes all those problems I was having with references.

Thank you !!

word - it’s what I thought - all the issues are solved by pass by reference —

great - that code + additions is coming up soon

thanks for being patient and testing !
z

Here are two things in my older opencv addon that now breaks, perhaps they could be included in the new version? (ive fixed them on the recent files now)

grayscaleImage = floatImage

  
  
void ofCvGrayscaleImage::operator =	( ofCvFloatImage & mom ){  
	if (mom.width == width && mom.height == height){  
		cvConvertScale( mom.getCvImage(), cvImage, 1, 0 );  
	} else {  
		// what do we do?  
		// cvResize?  
		// cvClone?  
		printf("error in =, images are different sizes\n");  
	}  
}  
  

grayscaleImage.median()

  
  
void ofCvGrayscaleImage::median(int _amount){  
	cvSmooth(cvImage, cvImageTemp, CV_MEDIAN, _amount);  
	swapTemp();  
}  
  

Just a suggestion. Thanks for all your help,

sure - we can get them in –

thanks!
zach