【问题标题】:OpenCV's cv::Mat & CvMat row alignmentOpenCV cv::Mat 到 Cv Mat 行对齐
【发布时间】:2011-05-16 20:49:16
【问题描述】:

有人可以向我解释一下 OpenCV 的 CvMat(或其 C++ 版本 cv::Mat)的行对齐是如何工作的吗?例如,假设我有一个矩阵

CvMat *cvmat = cvCreateMat(2,3,CV_8UC1);
cvSet2D( cvmat, 0, 0, cvScalar(1) );
cvSet2D( cvmat, 0, 1, cvScalar(2) );
cvSet2D( cvmat, 0, 2, cvScalar(3) );
cvSet2D( cvmat, 1, 0, cvScalar(4) );
cvSet2D( cvmat, 1, 1, cvScalar(5) );
cvSet2D( cvmat, 1, 2, cvScalar(6) );

根据CvMat 的文档,行应对齐 4 个字节,即矩阵的第一行应填充一个零,第二行应从偏移量 +4 开始)。但是,如果我调试这段代码,数据是连续的(即cvmat->data[1,2,3,4,5,6])并且我看不到任何 4 字节对齐。这是文档中的错误吗?假设CvMatcv::Mat 的数据的连续性总是安全的(如果矩阵不是另一个ofc 的一部分)?或者是否有一些特殊的配置可能会因为内存对齐而导致数据中存在一些间隙?

【问题讨论】:

    标签: opencv memory-alignment


    【解决方案1】:

    假设连续性是不安全的。 cv::Mat 有一个成员函数 isContinuous 可以检查连续性(C API 有一个宏,正如评论所说):

    // returns true iff the matrix data is continuous
    // (i.e. when there are no gaps between successive rows).
    // similar to CV_IS_MAT_CONT(cvmat->type)
    bool isContinuous() const;
    

    还有一个成员step 告诉你连续行之间的偏移量:

    // a distance between successive rows in bytes; includes the gap if any
    size_t step;
    

    因此,假设您有一个 8 位单通道图像,则 (x, y) 处的像素位于偏移量 y * step + x

    在许多情况下,您最终会得到不连续的内存,而且它们并不限于内存对齐。例如,如果您说cv::Mat r = mat.col(0),则不会复制数据,但r 指向与mat 相同的内存区域,只是具有不同的“标题”,因此您拥有的“间隙”就是数据来自不在第 0 列中的矩阵。

    【讨论】:

    • 也许我问错了问题。我知道cv::Mat 的成员以及矩阵可以是另一个矩阵的一部分的特殊情况。但我不明白的是 4 字节行对齐。因此,例如,我一直在编写所有 foreach(y,x) 嵌套 for 循环,其中指向第 y 行的指针在每次第 y 次迭代时重新初始化,这可能导致繁琐的代码和不必要的计算。 ..
    • 有了C++接口,代码其实并不繁琐。答案仍然存在——“假设连续性是不安全的”。如果实现确实碰巧使用了连续内存(例如,在多通道矩阵的情况下,iirc 就不会),那可能会在没有通知的情况下发生变化。
    • 我认为 step 只为 CvMat 定义,而对于 cv::Mat 你应该改用 step1() 方法
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多