opencv Mat在实际应用过程中注意的事项

C++ 的引用等操作区别

参考这篇文章

Mat的=操作符的赋值

定义函数

void sw(cv::Mat& a)
{
	a.at<uchar>(1,1)=10;
}
void sw1(cv::Mat a)
{
	a.at<uchar>(1,1)=20;
}
void sw2(cv::Mat& a,cv::Mat& b)
{
	cv::swap(a,b);
}

操作代码

    cv::Mat a=Mat::zeros(3,3,CV_8UC1);
	cv::Mat b=a;
	std::cout<<"a before sw:"<<std::endl<<a<<std::endl;
	std::cout<<"b before sw:"<<std::endl<<b<<std::endl;
	sw(a);
	std::cout<<"a after sw:"<<std::endl<<a<<std::endl;
	std::cout<<"b after sw:"<<std::endl<<b<<std::endl;
	sw1(a);
	std::cout<<"a after sw1:"<<std::endl<<a<<std::endl;
	std::cout<<"b after sw1:"<<std::endl<<b<<std::endl;

	cv::Mat c=Mat::ones(3,3,CV_8UC1);
	sw2(b,c);
	std::cout<<"a after sw2:"<<std::endl<<a<<std::endl;
	std::cout<<"b after sw2:"<<std::endl<<b<<std::endl;
	std::cout<<"c after sw2:"<<std::endl<<c<<std::endl;

	c.at<uchar>(1,1)=30;
	std::cout<<"a final:"<<std::endl<<a<<std::endl;
	std::cout<<"b final:"<<std::endl<<b<<std::endl;
	std::cout<<"c final:"<<std::endl<<c<<std::endl;
	

终端输出结果分析

  • b=a,浅拷贝此时只是新增了一个数据头b,但是b.data和a.data指向的同 一片区域,假设该区域为data1,则该区域的引用计数为2。经过函数sw因引用传递,所以在函数内部改变的是a.data的数据,同时b.data也会发生改变
  • 经过函数sw1,虽然不是引用传递,但传入a时相当于复制了一个a1,该操作是浅拷贝,只是新增了一个矩阵头,但a1.data与a.data指向的内存为data1,此时data1的引用计数为3(a,b,a1),所以改变a1.data的数据b.data,a.data也会发生改变,当函数结束后,a1作用域消失,此时data1的引用计数为2(a,b)
  • 定义一个矩阵c,假设c.data指向的区域为data2,经过sw2(b,c)之前有两个区域data1(a,b指向该区域) data1(c指向该区域),经过函数sw2(b,c),此时b.data的指针地址与c.data指针的地址进行了互换,但是b.data与c.data的数据没有修改,此时data1(a,c指向该区域) data1(b指向该区域),
  • 最终改变mat c的数据时,改变的是c.data的值,也就是data1的值,所以a的值也会改变
a before sw:
[  0,   0,   0;
   0,   0,   0;
   0,   0,   0]
b before sw:
[  0,   0,   0;
   0,   0,   0;
   0,   0,   0]
a after sw:
[  0,   0,   0;
   0,  10,   0;
   0,   0,   0]
b after sw:
[  0,   0,   0;
   0,  10,   0;
   0,   0,   0]
a after sw1:
[  0,   0,   0;
   0,  20,   0;
   0,   0,   0]
b after sw1:
[  0,   0,   0;
   0,  20,   0;
   0,   0,   0]
a after sw2:
[  0,   0,   0;
   0,  20,   0;
   0,   0,   0]
b after sw2:
[  1,   1,   1;
   1,   1,   1;
   1,   1,   1]
c after sw2:
[  0,   0,   0;
   0,  20,   0;
   0,   0,   0]
a final:
[  0,   0,   0;
   0,  30,   0;
   0,   0,   0]
b final:
[  1,   1,   1;
   1,   1,   1;
   1,   1,   1]
c final:
[  0,   0,   0;
   0,  30,   0;
   0,   0,   0]

总结

构造cv::Mat 对象时,除了clone()与CopyTo()这两个操作是深拷贝(会重新开辟一个内存空间与矩阵头)外,其余的都是浅拷贝,不会开辟内存空间,原mat与新mat矩阵数据指针指向同一个内存区域

发布了12 篇原创文章 · 获赞 3 · 访问量 738
展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 大白 设计师: CSDN官方博客

分享到微信朋友圈

×

扫一扫,手机浏览