如何在 OpenCV Mat 中保留固定的缓冲区大小

How can I reserve a fixed buffer size in OpenCV Mat?

本文关键字:缓冲区 保留 OpenCV Mat      更新时间:2023-10-16

我正在重写一些使用原始 C 样式数组对双精度进行矩阵运算的遗留代码。由于代码已经依赖于其他地方的 OpenCV,因此我想改用 cv::Mat 类。

困扰我的特定代码适用于大小从 1*1 到 N N 的方阵。它通过分配 N N个缓冲区并将其子集用于较小的矩阵来实现。

double* buf = new double[NxN];
for (int i = 1; i < N; ++i) {
    // Reuse buf to create a i*i matrix and perform matrix operations
    ...
}
delete[] buf;

基本上,我想替换该代码以使用循环中的cv::Mat对象。问题是,如果我只使用朴素而干净的方法,代码需要大量的循环迭代(有嵌套循环等(,并且分配/解除分配太多。因此,我想事先保留矩阵对象的大小,并为每次迭代调整其大小。理想情况下,这将如下所示:

cv::Mat m;
m.reserveBuffer(N * N * sizeof(double));
for (int i = 1; i < N; ++i) {
    m = cv::Mat(i, i, CV_64F);
    // Perform matrix operations on m
    ...
}

但据我了解,这只会删除之前的m实例,然后分配一个 i*i 矩阵。正确的方法是什么?

您可以使用

cv::Mat::operator() 为缓冲区创建 submatix 标头。传递要在当前循环迭代中处理的 ROI cv::Rect(在您的情况下{0, 0, i, i}(,它将返回缓冲区的视图作为另一个cv::Mat实例。它不会分配新的缓冲区,而是引用原始缓冲区数据。

cv::Mat m(N, N, CV_64FC1);
for (int i = 1; i < N; ++i) {
    cv::Mat subM = m({0, 0, i*i});
    // Perform matrix operations on "subM"
    // Modifying "subM" will modify "m" buffer region that "subM" represents
}

请注意,subM不会是连续的,因此如果执行任何原始缓冲区处理,则需要逐行处理它。