Ask Your Question

Revision history [back]

How to use Mat as a C++ member correctly?

Using VS 2012 with OpenCV 2.4.10

I am grabbing an image from a Basler camera in a thread class in my DLL and and converting it to an OpenCV Mat. I then pass it to an CameraImage class that is created using new and add it to a queue where another thread writes it out to disk and deletes the instance.

I find that whether I assign, clone(), copyTo(), or create/memcpy image to CameraImage.mImage when I delete the instance of CameraImage, mImage does not delete the image data and around the 86th image the create Mat throws an exception which means that it cannot allocate the memory for the new image. I thought the smart pointer takes care of the data memory allocation/deallocation automatically as well as refcount. I even call mImage.release() in the CameraImage destructor. I have used assert() to check on the refcount(s) (not shown).

Image grab class thread

void CImageWriter::Grab()
{
   ...
   mCamera.GrabImage(result);

   cv::Mat image;

   ConvertToMat(image, result.GetImage());
   CameraImage *cameraImage = new CameraImage(image);

   // Send it to the write queue thread.
   mWriteQueueThread.QueueToWrite(cameraImage);
   ...
}

Converting to Mat

void CImageWriter::ConvertToMat(cv::Mat &image, Pylon::IImage &pylonImage, ImageRotation rotateDegrees)
{
   Pylon::CImageFormatConverter converter;
   Pylon::CPylonImage target;

   converter.OutputPixelFormat = Pylon::PixelType::PixelType_BGR8packed;
   converter.OutputBitAlignment = Pylon::OutputBitAlignmentEnums::OutputBitAlignment_MsbAligned;
   converter.Convert(target, pylonImage);

   image.create(target.GetHeight(), target.GetWidth(), CV_8UC3);
   // copies from Result.Buffer into img 
   memcpy(image.ptr(), target.GetBuffer(), 3*target.GetWidth()*target.GetHeight());

   Rotate(image, image, rotateDegrees);
}

The Image Class

class CameraImage
{
public:
    CameraImage(cv::Mat &image);
    ~CameraImage();

    void WriteToDisk(void);

protected:
    cv::Mat mImage;
};


 CameraImage::CameraImage(cv::Mat &image)
 {
    mImage = image; or mImage = image.clone();  or  image.copyTo(mImage); 
    or
    mImage.create(image.rows, image.cols, CV_8UC3);
    memcpy(mImage.ptr(), image.ptr(), 3 * image.rows * image.cols);
 }

 CameraImage::~CameraImage()
 {
    mImage.release();
 }

Is this the proper way to use Mat as a C++ member? What am I doing wrong?

How to use Mat as a C++ member correctly?

Using VS 2012 with OpenCV 2.4.10

I am grabbing an image from a Basler camera in a thread class in my DLL and and converting it to an OpenCV Mat. I then pass it to an CameraImage class that is created using new and add it to a queue where another thread writes it out to disk and deletes the instance.

I find that whether I assign, clone(), copyTo(), or create/memcpy image to CameraImage.mImage when I delete the instance of CameraImage, mImage does not delete the image data and around the 86th image the create Mat throws an exception which means that it cannot allocate the memory for the new image. I thought the smart pointer takes care of the data memory allocation/deallocation automatically as well as refcount. I even call mImage.release() in the CameraImage destructor. I have used assert() to check on the refcount(s) (not shown).

Image grab class threadGrab function

void CImageWriter::Grab()
{
   ...
   mCamera.GrabImage(result);

   cv::Mat image;

   ConvertToMat(image, result.GetImage());
   CameraImage *cameraImage = new CameraImage(image);

   // Send it to the write queue thread.
   mWriteQueueThread.QueueToWrite(cameraImage);
   ...
}

Converting to Mat

void CImageWriter::ConvertToMat(cv::Mat &image, Pylon::IImage &pylonImage, ImageRotation rotateDegrees)
{
   Pylon::CImageFormatConverter converter;
   Pylon::CPylonImage target;

   converter.OutputPixelFormat = Pylon::PixelType::PixelType_BGR8packed;
   converter.OutputBitAlignment = Pylon::OutputBitAlignmentEnums::OutputBitAlignment_MsbAligned;
   converter.Convert(target, pylonImage);

   image.create(target.GetHeight(), target.GetWidth(), CV_8UC3);
   // copies from Result.Buffer into img 
   memcpy(image.ptr(), target.GetBuffer(), 3*target.GetWidth()*target.GetHeight());

   Rotate(image, image, rotateDegrees);
}

The Image Class

class CameraImage
{
public:
    CameraImage(cv::Mat &image);
    ~CameraImage();

    void WriteToDisk(void);

protected:
    cv::Mat mImage;
};


 CameraImage::CameraImage(cv::Mat &image)
 {
    mImage = image; or mImage = image.clone();  or  image.copyTo(mImage); 
    or
    mImage.create(image.rows, image.cols, CV_8UC3);
    memcpy(mImage.ptr(), image.ptr(), 3 * image.rows * image.cols);
 }

 CameraImage::~CameraImage()
 {
    mImage.release();
 }

Is this the proper way to use Mat as a C++ member? What am I doing wrong?

How to use Mat as a C++ member correctly?

Using VS 2012 with OpenCV 2.4.10

I am grabbing an image from a Basler camera in a thread class in my DLL and and converting it to an OpenCV Mat. I then pass it to an CameraImage class that is created using new and add it to a queue where another thread writes it out to disk and deletes the instance.

I find that whether I assign, clone(), copyTo(), or create/memcpy image to CameraImage.mImage when I delete the instance of CameraImage, mImage does not delete the image data and around the 86th image the create Mat throws an exception which means that it cannot allocate the memory for the new image. I thought the smart pointer takes care of the data memory allocation/deallocation automatically as well as refcount. I even call mImage.release() in the CameraImage destructor. I have used assert() to check on the refcount(s) (not shown).

Image Grab functionfunction called by thread

void CImageWriter::Grab()
{
   ...
   mCamera.GrabImage(result);

   cv::Mat image;

   ConvertToMat(image, result.GetImage());
   CameraImage *cameraImage = new CameraImage(image);

   // Send it to the write queue thread.
   mWriteQueueThread.QueueToWrite(cameraImage);
   ...
}

Converting to Mat

void CImageWriter::ConvertToMat(cv::Mat &image, Pylon::IImage &pylonImage, ImageRotation rotateDegrees)
{
   Pylon::CImageFormatConverter converter;
   Pylon::CPylonImage target;

   converter.OutputPixelFormat = Pylon::PixelType::PixelType_BGR8packed;
   converter.OutputBitAlignment = Pylon::OutputBitAlignmentEnums::OutputBitAlignment_MsbAligned;
   converter.Convert(target, pylonImage);

   image.create(target.GetHeight(), target.GetWidth(), CV_8UC3);
   // copies from Result.Buffer into img 
   memcpy(image.ptr(), target.GetBuffer(), 3*target.GetWidth()*target.GetHeight());

   Rotate(image, image, rotateDegrees);
}

The Image Class

class CameraImage
{
public:
    CameraImage(cv::Mat &image);
    ~CameraImage();

    void WriteToDisk(void);

protected:
    cv::Mat mImage;
};


 CameraImage::CameraImage(cv::Mat &image)
 {
    mImage = image; or mImage = image.clone();  or  image.copyTo(mImage); 
    or
    mImage.create(image.rows, image.cols, CV_8UC3);
    memcpy(mImage.ptr(), image.ptr(), 3 * image.rows * image.cols);
 }

 CameraImage::~CameraImage()
 {
    mImage.release();
 }

Is this the proper way to use Mat as a C++ member? What am I doing wrong?