Reputation:
I meet this problem when I deal with image streams from multi-cameras. I create a map and put all images into it based on the camera id, so I have:
std::mat<uint32_t, cv::Mat> images;
I will add image into that map by calling addImages
as soon as receiving data from a specific camera:
void addImages(uint32_t camera_id, CameraData imgData)
{
cv::Mat img = cv::Mat(imgData.height(), imgData.width(), CV_8UC3, (void *)imgData.ptr);
images.insert(make_pair(camera_id, img));
cv::imshow("origin image", img);
}
When I show images from that map somewhere else, strange thing happens. The image changes and I can tell that its color differs from the original one.
void showImage(uint32_t camera_id)
{
cv::imshow("get image", images[camera_id]);
cv::waitKey(1);
}
But when I change addImages
codes a little bit, images are same as original ones which is expected.
void addImages(uint32_t camera_id, CameraData imgData)
{
cv::Mat img = cv::Mat(imgData.height(), imgData.width(), CV_8UC3, (void *)imgData.ptr);
// NOTE THIS LINE!!!
images.insert(make_pair(camera_id, img.clone()));
cv::imshow("origin image", img);
}
So, my question is, what is the difference? Is there any other way to solve this problem?
Upvotes: 0
Views: 313
Reputation: 87959
This line seems incorrect.
cv::Mat img = cv::Mat(imgData.height(), imgData.width(), CV_8UC3, (void *)imgData.ptr);
Here's a quote from the documentation on the fourth parameter to this constructor
Pointer to the user data. Matrix constructors that take data and step parameters do not allocate matrix data. Instead, they just initialize the matrix header that points to the specified data, which means that no data is copied.
In other words the Mat
object just stores this pointer, it doesn't copy the data from it.
Now when your addImages
function exits it destroys the imgData
object which (presumably) invalidates the pointer you have just stored in the img
object. That results in the problem you see.
The second version creates a clone of the img
object which does copy the image data and so breaks the connection between the img
object and the imgData
object.
You might be able to fix this problem by passing the imgData
parameter by reference. This means the imgData
object would not be destroyed at the end of the function. But you would still have a situation where the Mat
object and the CameraData
object are sharing image data. So that might not be a good solution, but only you could say that for sure.
Upvotes: 2