c++ - 将 cv::Mat 插入 std::map 后会改变吗?根本原因是什么?
问题描述
当我处理来自多相机的图像流时,我遇到了这个问题。我创建了一张地图并根据相机 ID 将所有图像放入其中,所以我有:
std::mat<uint32_t, cv::Mat> images;
addImages
一旦从特定相机接收数据,我将通过调用将图像添加到该地图中:
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);
}
当我在其他地方显示该地图的图像时,会发生奇怪的事情。图像发生了变化,我可以看出它的颜色与原始颜色不同。
void showImage(uint32_t camera_id)
{
cv::imshow("get image", images[camera_id]);
cv::waitKey(1);
}
addImages
但是当我稍微更改代码时,图像与预期的原始图像相同。
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);
}
所以,我的问题是,有什么区别?有没有其他方法可以解决这个问题?
解决方案
这条线似乎不正确。
cv::Mat img = cv::Mat(imgData.height(), imgData.width(), CV_8UC3, (void *)imgData.ptr);
这是此构造函数的第四个参数的文档中的引用
指向用户数据的指针。采用数据和步骤参数的矩阵构造函数不分配矩阵数据。相反,它们只是初始化指向指定数据的矩阵头,这意味着没有数据被复制。
换句话说,Mat
对象只是存储这个指针,它不会从中复制数据。
现在,当您的addImages
函数退出时,它会破坏imgData
(可能)使您刚刚存储在对象中的指针无效的img
对象。这会导致您看到的问题。
第二个版本创建了一个img
对象的克隆,它确实复制了图像数据,因此中断了img
对象和imgData
对象之间的连接。
您可以imgData
通过引用传递参数来解决此问题。这意味着imgData
对象不会在函数结束时被销毁。但是您仍然会遇到Mat
对象和CameraData
对象共享图像数据的情况。所以这可能不是一个好的解决方案,但只有你可以肯定地说。
推荐阅读
- php - PHP命令行字符串添加
- python - 使用 Python 进行有效的滚动修剪均值
- python - 用张量流求解函数方程
- laravel-5 - 在 `AppServiceProvider` 类中使用 auth('api')->user() 时返回 null
- android - 如何为recyclerview制作书签列表?
- c++ - cmake 和 /opt/cmake/bin/cmake 显示不同的版本
- css - ASP.NET 内部风格不知从何而来
- ruby-on-rails - Active Model Serializer - 序列化具有多个键和值的模型
- c# - PrintPreviewDialog 仅显示 1 页的项目数少于正在打印的项目数
- css - 展开不同形状和大小的三角形?