В следующем коде я хотел бы присвоить значения элементам переменной Mat в цикле. Я получаю ошибку времени выполнения ниже.
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
Спасибо за ваши ответы.
меняя ymat.at<int>(i, j) = i;
на ymat.at<uchar>cv::Point(i, j) = i;
@YunusTemurlenk - Я думаю, что помимо использования at
в коде есть еще некоторые проблемы. Смотрите мой ответ ниже.
@wohlstad Это единственная ошибка, которую я видел. но ваш ответ указывает и на другие ошибки. Я подниму твой ответ;)
Я предполагаю, что вы хотели сгенерировать вывод, аналогичный numpy.meshgrid
и Матлаб meshgrid
.
В вашем коде есть несколько ошибок:
cv::Mat
инициализируется типом CV_16U (т. е. 16-битным значением без знака), но когда вы получаете доступ к элементам с помощью at
, вы используете int
(32-битное знаковое значение).
Вы должны изменить его на at<unsigned short>
(или изменить тип cv::Mat
на 32-битный знак - CV_32S
).cv::Mat
неправильными размерами: xmat
имеет размер (sy, sx)
, но ymat
имеет размер (sy, sy)
.rows
, cols
,
и индексы цикла к iRow
, iCol
.x
и y
(а не индексов).См. обновленный код ниже (и примечания после него относительно изменений):
#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
Некоторые примечания:
cv::Mat
. Но, по крайней мере, теперь у вас есть код, который не дает сбоев. Вы можете изменить присвоенные значения по своему усмотрению.at
для доступа к cv::Mat
элементам один за другим очень неэффективно, потому что at
содержит некоторые проверки для каждого доступа.
Гораздо эффективнее использовать метод cv::Mat
ptr
, который дает вам указатель на данные строки. Затем вы можете использовать этот указатель для более эффективного обхода строки - см. вышеcv::Mat
одну строку за другой (а не столбец за столбцом). Это заставляет вас обращаться к непрерывной памяти и уменьшает количество промахов кеша.meshgrid
будет создавать только матрицы. Распечатайте их снаружи, если вам нужно.cv::Mat
единицами, потому что сразу после этого мы устанавливаем значения для всех элементов.x
и y
передаются функции по константной ссылке. Это более эффективно (избегайте копирования), а также заставляет компилятор проверять, что векторы не изменены.using namespace std
- см. здесь Почему «используется пространство имен std;» считается плохой практикой?.
По аналогичным причинам я также рекомендую избегать using namespace cv
.Спасибо, ваше решение работает, это из-за несоответствия в типе данных, который получает cv::Mat.
Вы программируете на C++. Пожалуйста, не добавляйте другие нерелевантные языковые теги.