前置知识
1、Mat 类包含两部分,一是 矩阵头 (matrix header),二是 矩阵指针 (pointer to matrix)
2、 Mat 类中的赋值算子 "=" 和 拷贝构造函数,涉及的是浅拷贝,当执行这两个操作时,仅仅是复制了矩阵头。
参考链接:OpenCV 之 Mat 类 - 飞鸢逐浪 - 博客园
场景一
直接在函数里创建一个cv::Mat对象,并返回。这里借助了C11的返回值优化技术,只会有一个拷贝构造。
cv::Mat bgr = cv::imread("lena.jpg") // 使用拷贝构造函数
// OpenCV 4.5.2 imread源码
// modules/imgcodecs/src/loadsave.cpp
Mat imread( const String& filename, int flags )
{
CV_TRACE_FUNCTION();
/// create the basic container
Mat img;
/// load the data
imread_( filename, flags, img );
/// return a reference to the data
return img;
}
场景二
将现有的对象,赋予新值,减少代码变量。
cv::Mat bgr_to_rgb(const cv::Mat& bgr)
{
Mat rgb;
cv::cvtColor(bgr, rgb, cv::COLOR_BGR2RGB);
return rgb;
}
cv::Mat image = cv::imread("lena.jpg");
image = bgr_to_rgb(image); // 使用赋值函数
// OpenCV 4.5.2 cv::Mat的赋值操作符重载源码,添加了说明注释
// modules/core/src/matrix.cpp
Mat& Mat::operator=(const Mat& m)
{
if( this != &m )
{
if( m.u )
CV_XADD(&m.u->refcount, 1);
release(); // 释放现有对象,如果无其它引用,会释放数据块内存空间
flags = m.flags;
if( dims <= 2 && m.dims <= 2 )
{
dims = m.dims;
rows = m.rows;
cols = m.cols;
step[0] = m.step[0];
step[1] = m.step[1];
}
else
copySize(m);
data = m.data; // 与赋值的Mat共享数据块,浅复制只复制指针
datastart = m.datastart;
dataend = m.dataend;
datalimit = m.datalimit;
allocator = m.allocator;
u = m.u;
}
return *this;
}
总结
1、加深对C++里拷贝构造函数和赋值函数的理解
2、查看OpenCV源码,可以加深使用的认识,写出安全又优雅的代码