运行 使用 cv::Mat::at 分配 cv::Mat 元素值时出错
Run time error assigning cv::Mat element value using cv::Mat::at
在下面的代码中,我想在循环中为 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
感谢您的回答。
我假设您打算生成类似于 numpy.meshgrid
, and Matlab 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)
.
- 您用来访问 mat 元素的索引(行、列)不正确。为了更容易正确使用,我将尺寸的名称更改为
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
效率更高。这会导致您访问连续内存,并减少高速缓存未命中的次数。
- 在您的实际代码中,最好将计算与 I/O 分开。因此,如果您的
meshgrid
函数只创建矩阵会更好。如果需要,请打印出来。
- 无需将
cv::Mat
初始化为 1,因为之后我们会立即设置所有元素的值。
- 在我的代码中,
x
和 y
通过常量引用传递给函数。它更有效(避免复制)并且还强制编译器验证向量未被修改。
- 最好避免
using namespace std
- 请参阅此处 Why is "using namespace std;" considered bad practice?。
出于类似的原因,我也建议避免 using namespace cv
。
在下面的代码中,我想在循环中为 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
感谢您的回答。
我假设您打算生成类似于 numpy.meshgrid
, and Matlab 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)
. - 您用来访问 mat 元素的索引(行、列)不正确。为了更容易正确使用,我将尺寸的名称更改为
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
效率更高。这会导致您访问连续内存,并减少高速缓存未命中的次数。 - 在您的实际代码中,最好将计算与 I/O 分开。因此,如果您的
meshgrid
函数只创建矩阵会更好。如果需要,请打印出来。 - 无需将
cv::Mat
初始化为 1,因为之后我们会立即设置所有元素的值。 - 在我的代码中,
x
和y
通过常量引用传递给函数。它更有效(避免复制)并且还强制编译器验证向量未被修改。 - 最好避免
using namespace std
- 请参阅此处 Why is "using namespace std;" considered bad practice?。 出于类似的原因,我也建议避免using namespace cv
。