我可以为OpenCV矩阵提供只读访问权限吗?

3

我有一个类,它结合了许多OpenCV的cv::Mat矩阵。

是否有任何方法可以提供const访问器,允许客户端读取而不写入底层数据,并提供非const访问器,允许客户端读取和写入数据。

我考虑做这样的事情:

class MyClass {
    cv::Mat a;

public:
    cv::Mat a() { return a; }
    const cv::Mat& a() const { return a; }
};

但是这是否能保护通过const访问器被修改的底层数据呢?还是只能保护cv::Mat的头部数据?


1
实际上,您可以通过查找cv :: Mat的参考资料并查看声明为const的成员函数来自行检查。这些函数可以在a()返回的值上调用。如果有一些返回对底层数据的非const句柄,则不行。否则,可以。(虽然我希望有人能确认一下)。 - JBL
不错的观点,但复制构造函数的签名应该是cv::Mat(const cv::Mat& other)。然而,根据标准行为,我知道这样会允许您修改原始矩阵的底层数据。 - Tim MB
这要看情况。如果您没有提供复制构造函数,C++会为您生成一个,它将使用相应成员变量(即copy.member1将使用source.member1的值进行初始化)来初始化每个成员变量。从这一点出发,这取决于成员类型。如果成员变量不是指针,则很有可能实际上会进行复制,而不是放弃对要保护的数据的指针。 - JBL
是的 - 我在这里确实是在问指针的情况。OpenCV的矩阵在堆上分配所有数据,并使用引用计数在副本之间共享数据。 - Tim MB
确实,查看cv :: Mat头文件,它们复制数据指针。那么,如果它们没有提供任何不使用相同数据的复制方式,那将非常奇怪...然后,我不是专家,您是否尝试过您的代码以查看它是否在使用由a()返回的const引用创建矩阵时实际修改了两个矩阵? - JBL
1个回答

2
如果你被迫提供对cv::Mat对象本身的访问权限,那么你就没有办法了。即使在const cv::Mat上也可以通过data指针访问数据。因此,以下代码:
const cv::Mat test = cv::Mat::ones(3, 3, CV_8UC1);
test.data[3] = 4;

可以编译并执行。

但是,如果您只需要提供对数据的访问权限,则可以提供包装器函数cv::Mat::begin()cv::Mat::end(),这些函数允许在const cv::Mat上进行只读访问:

class MyClass
{
    cv::Mat a;

public:
    cv::MatIterator_<uchar> begin() {return a.begin<uchar>();}
    cv::MatConstIterator_<uchar> begin() const {return a.begin<uchar>();}

    cv::MatIterator_<uchar> end() {return a.end<uchar>();}
    cv::MatConstIterator_<uchar> end() const {return a.end<uchar>();}
};

MyClass m;    
const MyClass& mref = m;    
auto it = mref.begin();
*it = 4;                //Compile error here

在这个例子中,我使用了uchar作为数据类型,但很容易将其传递给模板参数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接