简体   繁体   English

C ++ / cv :: Mat相当于使用memcpy创建IplImage

[英]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: 我被传递了一些代码,其中使用memcpy创建了IplImage,然后转换为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. memory是指向内存块开头的void指针。

I want to port this code to use only the OpenCV C++ Api. 我想将此代码移植到仅使用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. 这种方法有效,但它占用了更多的RAM(大约100mb),所以我猜有一些不必要的复制。

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: EDIT2:这是完整的代码,包括内存来自的对象:

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. 问题是当矩阵仍然有效时, memory->getSharedMemory()中的数据被释放。

OpenCV creates a matrix header on the underlying data, but doesn't have control over it. OpenCV在基础数据上创建矩阵标头,但无法控制它。 So you need to make a deep copy of those underlying data. 因此,您需要对这些基础数据进行深层复制。 Easiest way is to use clone() : 最简单的方法是使用clone()

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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