ofxCv, toOf, toCv, ofImage::saveImage and crash

Hi
It’s a while I’m not using OF and C++ and I’m a bit rusty.

I’m facing with a EXC_BAD_ACCESS (SIGSEGV) while saving an image, and don’t understand exactly why.

What I’m trying to do:

  • load image
  • elaborate it with opencv
  • save it

for loading and saving I’m trying to stay on standard OF routines (ofImage::loadImage and ofImage::saveImage) while elaboration with opencv. Don’t know if it is the best way but I don’t see anything wrong on it.

Saving causes the crash.

This is my code:

------------------------------------------------------------------------------------- cpp:

#include "SpikeSave.h"

using namespace cv;
using namespace ofxCv;

void SpikeSave::setup(){
    String fileinput = "/path/to/image.JPG";
    original.loadImage(fileinput);

    Mat img = toCv(original);
    Mat out2;

    // some intense elaboration here..
    bitwise_not(img, out2);

    toOf(out2, original);
    original.update();
}

void SpikeSave::draw(){
    ofSetColor(255,255,255);
    original.draw(0, 0, 864, 576);
}

void SpikeSave::keyPressed(int key){
    if(key=='s') {
        string filename = ofGetTimestampString()+".png";
        std::cout << "save to "<< filename <<std::endl;

        std::cout << "original size: "<< original.width << " " << original.height <<std::endl;
        original.update();
        original.saveImage(filename);
    }
}

void SpikeSave::update(){}
void SpikeSave::keyReleased(int key){}
void SpikeSave::mouseMoved(int x, int y){}
void SpikeSave::mouseDragged(int x, int y, int button){}
void SpikeSave::mousePressed(int x, int y, int button){}
void SpikeSave::mouseReleased(int x, int y, int button){}
void SpikeSave::windowResized(int w, int h){}
void SpikeSave::gotMessage(ofMessage msg){}
void SpikeSave::exit(){}
void SpikeSave::dragEvent(ofDragInfo dragInfo){}

------------------------------------------------------------------------------------- h:

#pragma once

#include "ofMain.h"
#include "ofxCv.h"
#include "ofxUI.h"

class SpikeSave : 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);
        void dragEvent(ofDragInfo dragInfo);
        void gotMessage(ofMessage msg);
        void exit();

    private:
        ofImage original;
};

Just for information I’m on a mac os/x, compiling with Qtcreator, OF 0.8.0, opencv 2.3 (the one imported with ofxOpenCV)

Hi, I didn’t run the code but probably you need to

original.saveImage(ofToDataPath(filename));

when you save :wink:

Hi @micuat thanks for the reply… No… it is indeed a best practice but it is not the problem. Some trials (for example commenting out the opencv steps) save anyway the image…

mhmmmm…

if I use Mat out2 as a global (class variable declared in the .h file) it doesn’t crash anymore.

so this explains why:
toOf function does not make a deep copy of the image data. also, looking at the code of toOf: mat.ptr() is invoked… it pass only the pointer and after the scope of setup method is closed Mat out2 is deleted so calling it with sameImage freezes the program: the image data should be persistent.

but is not still clear: why do I see the matrix correctly in the draw?

and this is how to make a deep copy of the ofImage

original.loadImage(fileinput);

// toCv does not make a copy
Mat img = toCv(original);
Mat out2;

// some intense elaboration here..
bitwise_not(img, out2);

// toOf does not make a copy, pass only the pointer
ofImage tmp;
toOf(out2, tmp);

// ofImage::clone make a deep copy
original.clone(tmp);
original.update();

is there a better way? more efficient? how can I avoid the tmp image and put the image data from the opencv mat directly to the first image?..if I got correctly how it works: I should put the image data from the cv::Mat directly to the OpenGL texture, is it right?