0

我使用了 OpenCv,并在类似于以下代码的代码中使用了它:

Mat Create()
{ 
     Mat myMat(10, 10, CV8U_C1);    
     int x=myMat.Rows; // I am accessing Mat like an object not a pointer. 
     Return myMat;
 }

 Main()
 {
       Mat aMat=Create(); // created inside this function
       int x=aMat.Rows; // accessing it using . notation
       // do some work
       return;   //I did not delete Mat, as it would release its memory.
 }

如何在我的 C++ 代码中创建类似的对象?

我正在使用 STL,但如果需要,我也可以使用 Boost。

4

3 回答 3

5

首先std::vectorMat、 和其他数据结构具有析构函数,可在需要时释放底层内存缓冲区。这意味着析构函数并不总是像Mat. 他们考虑了可能的数据共享。析构函数递减与矩阵数据缓冲区关联的引用计数器。当且仅当引用计数器达到零时,才会释放缓冲区。也就是说,当没有其他结构引用同一个缓冲区时。同样,当一个Mat实例被复制时,并没有真正复制任何实际数据。相反,引用计数器会增加以记住相同数据的另一个所有者。还有Mat::clone()一种方法可以创建矩阵数据的完整副本。

于 2013-06-19T15:32:48.263 回答
4

其他答案是正确的 -cv::Mat是一个资源拥有对象std::vector<>,可以传递并按值返回。然而,有一种非常重要的方式cv::Mat表现得像一个指针,那就是它的别名行为。对于大多数类型T,以下情况是正确的:

T orig = initial_value;
T copy = orig;
mutate(copy);
assert(orig == initial_value);

也就是说,对于大多数类型,副本是独立的。你可以改变一个而不影响另一个。这对cv::Mat. 相反,你必须注意这样的事情:

cv::Mat orig = /* ... matrix of all zeros ... */
cv::Mat copy = orig; // NOTE! Creates an alias, not a copy.
copy(2,2) = 42;
assert(orig(2,2) == 42); // Huh.

看?更改副本更改了原件。从技术上讲,cv::Mat它不是常规类型,这很遗憾,因为包括 STL 在内的大多数现代 API 都假定类型是常规的。使用cv::Mat,事物会默默地别名化,从而导致难以找到、令人毛骨悚然的远距离动作类型的错误。使用cv::Mat要格外小心。并且永远不会使用 STL 算法和容器。

于 2013-06-19T20:04:22.987 回答
1

只需快速查看API 参考即可回答您的问题

class CV_EXPORTS Mat
{
public:
    // ... a lot of methods ...
    ...

最好的办法是阅读Mat 上的 OpenCV 教程

关于 Mat 你需要知道的第一件事是你不再需要手动分配它的内存并在你不需要它时立即释放它。...

Mat 基本上是一个包含两个数据部分的类:矩阵头(包含诸如矩阵大小、用于存储的方法、存储的矩阵的地址等信息)和指向包含像素值...

于 2013-06-20T07:36:02.183 回答