运行时间错误使用CV :: Mat :: AT分配CV :: MAT元素值

发布于 2025-01-28 09:32:56 字数 1353 浏览 4 评论 0原文

在以下代码中,我想为循环中垫变量的元素分配一个值。我在下面遇到运行时错误。

pair<Mat, Mat> meshgrid(vector<int> x, vector<int> y) {

    int sx = (int)x.size();
    int sy = (int)y.size();
    
    Mat xmat = Mat::ones(sy, sx, CV_16U);
    Mat ymat = Mat::ones(sy, sy, CV_16U);

    for (int i = 0; i < sx; i++) {
        for (int j = 0; j < sy; j++) {
            xmat.at<int>(i, j) = j;  // <------- here is place of error.
            cout << j << "\t";
        }
        cout << endl;
    }

    for (int i = 0; i < sx; i++) {
        for (int j = 0; j < sy; j++) {
            ymat.at<int>(i, j) = i;  // <------- here is place of error.
            cout << j << "\t";
        }
        cout << endl;
    }

    return make_pair(xmat, ymat);
}

调试时的这张照片;

这是我收到的运行时间错误:

OpenCV(...) Error: Assertion failed
(((((sizeof(size_t)<<28)|0x8442211) >> ((traits::Depth<_Tp>::value) &
((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
...\include\opencv2\core\mat.inl.hpp, line 1108

谢谢您的回答。

In the following code I would like to assign a values to elements of a Mat variable in a loop. I get the runtime error below.

pair<Mat, Mat> meshgrid(vector<int> x, vector<int> y) {

    int sx = (int)x.size();
    int sy = (int)y.size();
    
    Mat xmat = Mat::ones(sy, sx, CV_16U);
    Mat ymat = Mat::ones(sy, sy, CV_16U);

    for (int i = 0; i < sx; i++) {
        for (int j = 0; j < sy; j++) {
            xmat.at<int>(i, j) = j;  // <------- here is place of error.
            cout << j << "\t";
        }
        cout << endl;
    }

    for (int i = 0; i < sx; i++) {
        for (int j = 0; j < sy; j++) {
            ymat.at<int>(i, j) = i;  // <------- here is place of error.
            cout << j << "\t";
        }
        cout << endl;
    }

    return make_pair(xmat, ymat);
}

This picture when debuging;

enter image description here

This is the run time error I get:

OpenCV(...) Error: Assertion failed
(((((sizeof(size_t)<<28)|0x8442211) >> ((traits::Depth<_Tp>::value) &
((1 << 3) - 1))*4) & 15) == elemSize1()) in cv::Mat::at, file
...\include\opencv2\core\mat.inl.hpp, line 1108

Thank you for your answers.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

寻找一个思念的角度 2025-02-04 09:32:56

我假设您打算生成类似于 /code> matlab matlab meshgrid meshgrid

您的代码中有几个错误:

  1. cv :: mat使用类型CV_16U初始化(即16位无符号值),但是当您使用 at 访问元素时,您会使用int(为32位签名)。
    您应该将其更改为at&lt; unsigned Short&gt;(或将cv :: mat的类型更改为32位签名 - cv_32s)。
  2. 您初始化了cv :: mat带错误的大小:xmat的大小为 (sy,sx) ,但是ymat的大小为 (SY,SY)
  3. 您用来访问垫子元素的索引(行,col)不正确。为了使其更易于正确使用,我将装饰的名称更改为cols
    循环索引IROWICOL
  4. 矩阵中的值应来自xy向量(而不是索引)中的值。

请参阅下面的更新代码(以及有关更改的下面的注释):

#include <opencv2/core/core.hpp>
#include <vector>
#include <iostream>

std::pair<cv::Mat, cv::Mat> meshgrid(std::vector<unsigned short> const & x, std::vector<unsigned short> const & y)
{
    int cols = static_cast<int>(x.size());
    int rows = static_cast<int>(y.size());
    cv::Mat xmat(rows, cols, CV_16U);
    cv::Mat ymat(rows, cols, CV_16U);

    for (int iRow = 0; iRow < rows; ++iRow) {
        auto * pRowData = xmat.ptr<unsigned short>(iRow);
        for (int iCol = 0; iCol < cols; ++iCol) {
            pRowData[iCol] = x[iCol];
            std::cout << pRowData[iCol] << "\t";
        }
        std::cout << std::endl;
    }

    std::cout << std::endl;

    for (int iRow = 0; iRow < rows; ++iRow) {
        auto * pRowData = ymat.ptr<unsigned short>(iRow);
        for (int iCol = 0; iCol < cols; ++iCol) {
            pRowData[iCol] = y[iRow];
            std::cout << pRowData[iCol] << "\t";
        }
        std::cout << std::endl;
    }

    return std::make_pair(std::move(xmat), std::move(ymat));
}

int main()
{
    std::vector<unsigned short> xxx{ 1,2 };
    std::vector<unsigned short> yyy{ 10,11,12 };
    auto p = meshgrid(xxx, yyy);
    return 0;
}

输出:

1       2
1       2
1       2

10      10
11      11
12      12

一些注释:

  1. 我可能会误解您要在cv :: mat's中设置的值。但是至少现在您的代码不会崩溃。您可以根据需要更改分配的值。
  2. 使用at访问cv :: mat一个接一个的元素效率非常低,因为at包含每个访问的一些验证。
    使用cv :: mat方法ptr,它为您提供了一排数据的指针。然后,您可以使用此指针来更有效地穿越该行 - 请参见上文
  3. 以任何方法,遍历cv :: mat一排接头(而不是列列)更有效。这会导致您访问连续的内存,并减少缓存失误的数量。
  4. 在您的实际代码中,最好将计算与I/O分开。因此,如果您的meshgrid函数只会创建矩阵,那就更好了。如果需要,将它们打印在外面。
  5. 无需将cv :: mat s初始化,因为之后立即为所有元素设置值。
  6. 在我的代码xy中,通过const refernce传递给该函数。它更有效(避免复制),还迫使编译器验证向量未经修改。
  7. 最好避免使用命名空间std - 请参阅此处。为什么“使用名称空间std”;被认为是不好的做法吗?。
    从类似的原因中,我也推荐使用命名空间CV 避免

I assume you meant to generate output similar to numpy.meshgrid, and Matlab meshgrid.

There are several errors in your code:

  1. The cv::Mat is initialized with type CV_16U (i.e. 16 bit unsigned value), but when you access the elements with at you use int (which is 32bit signed).
    You should change it to at<unsigned short> (or change the type of the cv::Mat to 32 bit signed - CV_32S).
  2. You initialized the cv::Mat with wrong sizes: xmat has size of (sy, sx), but ymat has size of (sy, sy).
  3. The indices (row, col) you used to access the mat elements were incorrect. To make it easier to use correctly, I changed the names of the dimentions to rows, cols,
    and the loop indices to iRow, iCol.
  4. The values in the matrices should come from the values in x and y vectors (not the indices).

See updated code below (and the notes following it regarding the changes):

#include <opencv2/core/core.hpp>
#include <vector>
#include <iostream>

std::pair<cv::Mat, cv::Mat> meshgrid(std::vector<unsigned short> const & x, std::vector<unsigned short> const & y)
{
    int cols = static_cast<int>(x.size());
    int rows = static_cast<int>(y.size());
    cv::Mat xmat(rows, cols, CV_16U);
    cv::Mat ymat(rows, cols, CV_16U);

    for (int iRow = 0; iRow < rows; ++iRow) {
        auto * pRowData = xmat.ptr<unsigned short>(iRow);
        for (int iCol = 0; iCol < cols; ++iCol) {
            pRowData[iCol] = x[iCol];
            std::cout << pRowData[iCol] << "\t";
        }
        std::cout << std::endl;
    }

    std::cout << std::endl;

    for (int iRow = 0; iRow < rows; ++iRow) {
        auto * pRowData = ymat.ptr<unsigned short>(iRow);
        for (int iCol = 0; iCol < cols; ++iCol) {
            pRowData[iCol] = y[iRow];
            std::cout << pRowData[iCol] << "\t";
        }
        std::cout << std::endl;
    }

    return std::make_pair(std::move(xmat), std::move(ymat));
}

int main()
{
    std::vector<unsigned short> xxx{ 1,2 };
    std::vector<unsigned short> yyy{ 10,11,12 };
    auto p = meshgrid(xxx, yyy);
    return 0;
}

Output:

1       2
1       2
1       2

10      10
11      11
12      12

Some notes:

  1. I might have misunderstood which values you wanted to set in the cv::Mat's. But at least now you have code that does not crash. You can change the assigned values as you wish.
  2. Using at to access cv::Mat elements one after the other is very inefficient, because at contains some validations for every access.
    It's a lot more efficient to use the cv::Mat method ptr, that gives you a pointer to the data of a row. Then you can use this pointer to traverse the row more efficiently - see above
  3. In any method, it is more efficient to traverse a cv::Mat one row after another (and not column by column). This causes you to access continous memory, and decrease the number of cache misses.
  4. In your real code, it's better to separate calculations from I/O. Therefore it's better if your meshgrid function will only create the matrices. Print them outside if you need.
  5. No need to initialize the cv::Mats to ones, because immediatly afterwards we set the values for all elements.
  6. In my code x and y are passed to the function by const refernce. It is more efficient (avoid copy) and also forces the compiler to verify the vectors are not modified.
  7. Better to avoid using namespace std - see here Why is "using namespace std;" considered bad practice?.
    From similar reasons I recomend to avoid using namespace cv as well.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文