Using ofxCvImage , ofImage and Mat for images

Hi there,
I am trying to use backgroundSubtraction from opencv and I am unsure what is the efficient way to work with images and image containers.

I acquire frames as ofxCvGrayscaleImage and the backgroundSubtractor() works with 'cv::Mat ‘s’.

It is no problem to use ofxCv’s handy ‘toCv()’ to get a ‘cv::Mat’ out of ofxCvGrayscaleImage, but there is no ‘toOf()’ to allow processed Mat to be converted back to ofxCvGrayscaleImage.

As per ofxCv’s suggestion. to work with cv::Mat, I must declare an ofImage , get a Mat using toCv(), do my processing with the cv::Mat, and finally run ofImage::update() to register the changes in ofImage too.

So I have ended up the (slow!) following

1)use setFromPixels() to load the ofxCvGrayscaleImage into an ofImage.
2)create cv::Mat from ofImage
3)do processing with cv::Mat
4)update() the ofImage. (no assigning value back to the ofImage)
5)use setFromPixels() again to transfer the ofIamge back into ofxCvGrayscaleImage.

Well, the above works, but the FPS doesn’t go above 5. So the above is probably a very bad way of implement my algorithm. However, I am fuzzy about what would be a “good” and efficient way?

Thank you for your help!

if you are using ofxCv you don’t need to use ofxCvGrayscaleImage, just use ofPixels or ofImage directly. if you are using a videograbber or videoplayer you can just wrap the pixels into a Mat, when you use toCv you are not really converting the pixels into a Mat but just wrapping them so any transformation you apply will be in the original pixels too.

ofImage threshPixels;
ofVideoGrabber grabber;
...
Mat grabberMat = toCv(grabber.getPixelsRef());
Mat thresMat = toCv(threshold);
cv::threshold(grabberMat,threshMat,80);
thresPixels.update();

will leave the result of the thresholding directly in the ofImage

1 Like

this is where the key lies and I had never deduced.
I think i’ll remember from now on, considering the amount of changes I’ll have to carry out :smiley:

Thank you!

@arturo i am looking through the code snipet and have a question or 2.

  1. did you mean to write

    Mat thresMat = toCv(thresPixels)

also since grabbing and processing is done in separate classes for me , I wonder if it is “expensive” to deep copy the grabbed frame into an ofImage and use that to feed the input of the cv::operaiton. so the above would become:

ofImage threshPixels, grabbedFrame;
ofVideoGrabber grabber;
grabbedFrame.setFromPixels( grabber.getPixels() , w , h , OF_IMAGE_GRAYSCALE );
...
Mat grabberMat = toCv(grabbedFrame.getPixelsRef());
Mat thresMat = toCv(threshPixels);
cv::threshold(grabberMat,threshMat,80);
thresPixels.update();

yeah that’s it.

you can copy the pixels on an image but i don’t think you need to do that even if you have the code in different classes, at some point you are going to need to pass the image from one to another, so why not just pass the grabbers pixels or the grabber itself?, like

cvClass.update(grabber.getPixelsRef())

where

void cvClass::update(ofPixels & pixells){
...
}

Hello there!
I am trying to do something similar to the original poster. My problem is that toCV() seems to not be included in ofxCv anymore. Is that correct? or has is been renamed or something?

EDIT: Nevermind I misread that the function is only defined in ofxCv. I though it was in ofxOpenCv (which is a core addon). Anyways this would be a handy function to have in ofxOpenCv too.