fly*_*gip 26 c++ opencv deep-copy
复制的行为cv::Mat
让我很困惑.
我从文档中了解到Mat::copyTo()
深层复制,而赋值运算符则不是.我的问题:
我该怎么做才能cv::Mat
从函数中返回一个,比如:cv::Mat func()
?
根据文档,如果我返回cv::Mat
它将没有用,因为在函数返回后该函数的本地副本cv::Mat
将被销毁,因此接受函数外部返回值的那个应该指向一些随机地址.奇怪的是(大多数情况下)它正常工作.例如,以下工作:
cv::Mat CopyOneImage(const cv::Mat& orgImage)
{
cv::Mat image;
orgImage.copyTo(image);
return image;
}
int main()
{
std::string orgImgName("a.jpg");
cv::Mat orgImage;
orgImage = cv::imread(orgImgName);
cv::Mat aCopy;
aCopy = CopyOneImage(orgImage);
return 1;
}
Run Code Online (Sandbox Code Playgroud)但为什么?这不是一个深刻的副本.
问题3.有时,赋值运算符似乎也是深层复制:
int main()
{
std::string orgImgName("a.jpg");
cv::Mat orgImage;
orgImage = cv::imread(orgImgName);
cv::Mat aCopy;
orgImage.copyTo(aCopy);
cv::Mat copyCopy1;
copyCopy1 = aCopy;
cv::namedWindow("smallTest", 1);
cv::imshow("smallTest", copyCopy1);
uchar key = (uchar)cv::waitKey();
cv::Mat orgImage2 = cv::imread("b.jpg");
orgImage2.copyTo(aCopy);
cv::imshow("smallTest", copyCopy1);
return 1;
}
Run Code Online (Sandbox Code Playgroud)
然后两个显示器显示相同的图像,a.jpg.为什么?而有些时候它不起作用.(原始代码太长,但也可以简化为上述情况).在那些时候,赋值运算符实际上似乎是"浅"复制.为什么?
非常感谢!
And*_*dov 23
我认为,使用赋值不是矩阵复制的最佳方式.如果您想要矩阵的新完整副本,请使用:
Mat a=b.clone();
Run Code Online (Sandbox Code Playgroud)
如果你想复制矩阵来替换来自另一个矩阵的数据(为了避免内存重新分配),请使用:
Mat a(b.size(),b.type());
b.copyTo(a);
Run Code Online (Sandbox Code Playgroud)
当您为一个矩阵分配一个矩阵时,智能指针到矩阵数据的引用计数器增加1,当您释放矩阵时(它可以在离开代码块时隐式完成)它减1.当它变为等于零时,分配的内存被处理掉.
如果你想从函数使用引用得到结果它更快:
void Func(Mat& input,Mat& output)
{
somefunc(input,output);
}
int main(void)
{
...
Mat a=Mat(.....);
Mat b=Mat(.....);
Func(a,b);
...
}
Run Code Online (Sandbox Code Playgroud)
小智 7
我一直在使用OpenCV一段时间,而且cv :: Mat也让我很困惑,所以我做了一些阅读.
cv :: Mat是一个标题,指向一个保存实际图像数据的*数据指针.它还实现了引用计数.它保存cv::Mat
当前指向该*数据指针的标头数.因此,当您执行常规副本时,例如:
cv::Mat b;
cv::Mat a = b;
Run Code Online (Sandbox Code Playgroud)
a
将指向b
数据,并且它的引用计数将递增.同时,先前指向的数据的引用计数b
将递减(如果在递减之后它将为0,则将释放存储器).
问题1:这取决于您的计划.有关更多详细信息,请参阅此问题:is-cvmat-class-flawed-by-design
问题2:函数按值返回.这意味着return image
将复制Mat并增加引用计数(现在为ref_count = 2)并返回新的Mat.当函数结束时,图像将被销毁,ref_count将减少一个.但是由于ref_count不是0,因此不会释放内存.因此返回的cv :: Mat不指向随机内存位置.
问题3:类似的事情发生了.当你说orgImage2.copyTo(aCopy);
,指向的数据的ref_count aCopy
将减少.然后分配新内存来存储将要复制的新数据.这就是为什么copyCopy1
当你这样做时没有被修改的原因.