本文主要是介绍对cv::Mat进行容器push_back的理解,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
总所周知,cv::Mat 有两种拷贝方式,深拷贝和浅拷贝。直接a=b是浅拷贝,靠.clone()和copyTo()实现深拷贝。
容器的push_back是拷贝。
那么当我们push_back(cv::Mat)时,是深拷贝还是浅拷贝呢?
可以做一个实验,定义一个全局变量cv::Mat a , 全局变量vector<cv::Mat> buf;
不停更新a的值,发现buf里面都是最新的a的值。说明什么呢?说明**在push_bac Mat时是浅拷贝**
但是如果a是一个局部变量,则buf就是对的。这是由于cv::Mat的释放机制。
cv::Mat类似于智能指针的原理,有一个引用机制,有一个成员变量refcount,会自己根据被引用和释放的次数,自动管理内存。
push_back(cv::Mat) 浅拷贝,分配信息头,共享数据区,refcount++, 这时候局部变量a释放,只是清除本身的信息头和置零数据区指针,refcount--,由于refcount还不为零,共享数据区还不会被清空。
我认为如果生成cv::Mat容器,用局部变量来push_back是非常好的一种方式,即可以完成任务,又不耗时(clone耗时耗资源)。关键是能理解这种引用机制,只有一个引用没释放,这片内存就不会被释放!
需要注意的地方!!!
通过驱动(一般c语言编写)读取图片,一般是通过定义一个cv::Mat,其地址指向内存
cv::Mat gray(400, 640, CV_8UC1, buf->planes[0].start);
camera_put_image(handle, buf); //buf被释放了,即gray对应的内存被释放了
然后我们把gray可以浅拷贝给其他变量,push给buff之类的。按照cv::mat的内存管理机制,这里应该是没有什么问题的,前提啊,前提是buf->planes[0]不能释放,如果释放了,也就是所有cv::mat指向的那边内存被释放,一旦这片内存被使用,就会报错。
如果内存被释放,就不得不通过clone的方式给cv::mat重新申请一片内存。
因此我们一定要溯源,第一个mat的内存是什么样子的。可以用
cout << "img ptr" << gray.ptr<float>() << endl;
把mat对应的地址打出来看,我不知道为什么使用ptr<float>()才可以把地址打印出来。用uchar uint8都是乱码的。uint32_t是可以的。
这篇关于对cv::Mat进行容器push_back的理解的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!