简体   繁体   中英

C++ / cv::Mat equivalent of creating IplImage using memcpy

I was handed some code where an IplImage is created using memcpy and then converted to a cv::Mat:

IplImage* iplImage = cvCreateImage(cv::Size(imageWidth, imageHeight), IPL_DEPTH_8U, bytesPerPixel);
memcpy(iplImage->imageData, memory, imageWidth * imageHeight * bytesPerPixel);
cv::Mat image = cv::cvarrToMat(iplImage, true, true, 0);
cvReleaseImage(&iplImage);

memory is a void pointer to the beginning of a memory block.

I want to port this code to use only the OpenCV C++ Api. This is what I tried first:

cv::Mat image(cv::Size(imageWidth, imageHeight), CV_MAKETYPE(CV_8U, bytesPerPixel), memory);

But the image is empty.

Then I tried this:

cv::Mat image(cv::Size(imageWidth, imageHeight), CV_MAKETYPE(CV_8U, bytesPerPixel));
memcpy(image.data, memory, imageWidth * imageHeight * bytesPerPixel);

This method works, however it uses up a lot more RAM (about 100mb), so I guess there is some unnecessary copying involved.

What would be the correct way to do this?

EDIT: Memory is really in a wrapper class. It gets deallocated automatically. I changed it to just "memory" for simplicity.

EDIT2: Here is the complete code, including the object the memory comes from:

cv::Mat RecordingPlayer::next() {
    if (currentContainer.getDataType() == odcore::data::image::SharedImage::ID()) {
        odcore::data::image::SharedImage sharedImage = currentContainer.getData<odcore::data::image::SharedImage>();
        std::shared_ptr<odcore::wrapper::SharedMemory> memory = odcore::wrapper::SharedMemoryFactory::attachToSharedMemory(sharedImage.getName());
        IplImage* iplImage = cvCreateImage(imageSize(), IPL_DEPTH_8U, bytesPerPixel);
        memcpy(iplImage->imageData, memory->getSharedMemory(), imageWidth * imageHeight * bytesPerPixel);
        cv::Mat image = cv::cvarrToMat(iplImage, true, true, 0);
        cvReleaseImage(&iplImage);
        return image;
    } else {
        return cv::Mat();
    }
}

The issue is that data in memory->getSharedMemory() are deallocated while the matrix is still valid.

OpenCV creates a matrix header on the underlying data, but doesn't have control over it. So you need to make a deep copy of those underlying data. Easiest way is to use clone() :

cv::Mat image = Mat(cv::Size(imageWidth, imageHeight), CV_MAKETYPE(CV_8U, bytesPerPixel), memory->getSharedMemory()).clone(); 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM