cv :: Mat类是否在设计上存在缺陷? [英] Is cv::Mat class flawed by design?

查看:95
本文介绍了cv :: Mat类是否在设计上存在缺陷?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用OpenCV C ++接口进行了大量工作,并设计了许多使用Mat作为私有资源的类.

I work a lot with the OpenCV C++ interface and designed a number of classes which use Mat's as private resources.

最近,我担心Mat类,因为它总是使用图像数据作为共享资源,除非我明确调用clone. 即使我写了const Mat,也无法确定以后不会从外面更改图像数据.

Recently, I got concerned about the Mat class, as it always uses image data as shared resource unless I explicitly call clone. Even if I write const Mat I can't be sure that the imagedata does not get changed later from the outside.

所以我需要克隆以确保封装.但是需要显式克隆Mat的问题在于,它通常是不必要且昂贵的.另一方面,我了解对共享图像数据的需求源自roi选择器,并且能够编写如下内容: Mat m_small = m_big(my_roi).

So I need to clone to ensure encapsulation. But the problem with needing to explicitly clone a Mat is that it is often unnecessary and expensive. On the other hand I understand that the need for shared imagedata originates from roi selectors, and being able to write something like this: Mat m_small = m_big(my_roi).

我的问题是:

1.)是否应该懒惰地克隆cv :: Mat类?因此用户不会从外部将Mat视为共享资源处理程序.当需要真正的共享图像数据时,用户是否应该不显式实例化名为SharedMat之类的类?
2.)如果将cv :: Mat作为课程的私有资源,您是否有比总是克隆更好的策略?

1.) Should not the cv::Mat class be rather lazily cloned? So the user will not see Mat's as shared resource handlers from the outside. Should not the user explicitly instantiate a class called something like SharedMat when a real shared imagedata is needed?
2.) Do you have any better strategy than always cloning in case of cv::Mat as private resource for a class?

更新:除非计划修改数据,否则不要使用Mat::clone()." (由Vadim Pisarevsky撰写)
这个主意有问题. 考虑一下您上此类的情况:

UPDATE: "you do not use Mat::clone() unless you plan to modify the data." (by Vadim Pisarevsky)
This idea has a problem. Consider the situation that you have this class:

class Res_handler{
public:
  const Mat emit_mat(){ return m_treasure; } // I argue you are compelled to clone here.
private:
  Mat m_treasure;
};

如果您没有clone在这种情况下,您可以写

If you do not clone in this case you can write

Mat m_pirate = res_handler.emit_mat(); m_pirate = Scalar(0,0,0);

会通过m_piratem_treasure之间的共享图像数据在res_handler内部的m_treasure中造成完全黑屏. :)因此,为避免对内部进行意外修改,您需要对其进行clone .

which causes a full black-out in the m_treasure inside the res_handler through the shared image data between m_pirate and m_treasure. :) So to avoid accidental modification of the inner m_treasure, you need to clone it.

另一方面,此解决方案也有缺陷:

On the other hand, this solution is also flawed:

const Mat m_pirate = res_handler.emit_mat(); 

因为m_treasure也可以被修改,所以m_pirate的内容在后台被更改,这使海盗的程序员非常头痛. :)

because m_treasure can get modified too, so the content of m_pirate gets changed in the background, causing great headache to the pirate's programmer. :)

推荐答案

是的,这是一个较差的设计.由于Mat在内部实现共享所有权,因此它与选择所有权策略的标准方式(即智能指针)不兼容.基本问题是数据和所有权是正交的,应该分开.

Yes, this is a poor design. Because Mat implements shared ownership internally, it’s not compatible with the standard way of choosing ownership policy, namely smart pointers. The basic issue is that data and ownership are orthogonal, and ought to be separated.

因为它是可变的,所以即使const Mat也更像const shared_ptr<Mat>,无法描述所包含的Mat应该是可变的,即shared_ptr<const Mat>.如果您熟悉的话,这与Java中final的问题非常相似.

Because it is mutable, even a const Mat is more like a const shared_ptr<Mat>, with no way of describing that the contained Mat ought to be mutable, i.e., shared_ptr<const Mat>. This bears great similarity to the problems with final in Java, if you’re familiar.

我相信您可以通过将Mat包装在一个类中来解决这些问题,该类公开与Mat相同的接口,但是该类在默认的共享实现之上实现了写时复制行为.

I believe you can skirt these issues by wrapping Mat in a class that exposes the same interface as Mat, but which implements copy-on-write behaviour atop the default shared implementation.

这篇关于cv :: Mat类是否在设计上存在缺陷?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆