如何正确使用cv::Mat::at<double>(i,j,k)访问多通道矩阵?
如何正确使用cv::Mat::at(i,j,k)访问多通道矩阵元素?
测试代码
#include <iostream> #include <opencv2/highgui/highgui.hpp> int main() { double m[1][4][3] = { {{1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0}, {10.0, 11.0, 12.0}}}; cv::Mat M(1, 4, CV_64FC3, m); for (int i = 0; i < 1; ++i) for (int j = 0; j < 4; ++j) for (int k = 0; k < 3; ++k) std::cout << M.at<double>(i, j, k) << std::endl; cv::namedWindow("Input", cv::WINDOW_NORMAL); cv::imshow("Input", M); cv::waitKey(); return 0; }
预期输出
1.0 2.0 3.0 4.0 5.0 6.0 7.0 8.0 9.0 10.0 11.0 12.0
当前输出
1 8.10465e-320 5.31665e-315 4 8.11058e-320 2.122e-314 7 8.11355e-320 -9.44163e+21 10 7.16685e-308 0
问题原因与解决方法
你当前的写法错误在于:OpenCV的2D多通道矩阵不能用at<double>(i,j,k)来访问通道元素。这里的k会被误认为是3D矩阵的第三个维度索引,但你的矩阵是2D结构(1行4列,3通道),并非3D矩阵,这种访问方式会直接越界读取内存,导致输出垃圾值。
针对多通道矩阵的元素访问,推荐两种正确方式:
方式一:使用对应通道数的向量类型访问(推荐)
对于CV_64FC3类型的矩阵,每个像素是包含3个double的向量,对应OpenCV的cv::Vec3d类型。通过at<cv::Vec3d>(i,j)获取像素的向量值,再通过索引访问单个通道:
for (int i = 0; i < 1; ++i) for (int j = 0; j < 4; ++j) { cv::Vec3d pixel = M.at<cv::Vec3d>(i, j); for (int k = 0; k < 3; ++k) std::cout << pixel[k] << std::endl; }
方式二:通过内存偏移直接访问单个通道
如果坚持用double类型访问,可以利用OpenCV行优先的内存存储规则,计算通道的内存偏移位置:
for (int i = 0; i < 1; ++i) for (int j = 0; j < 4; ++j) for (int k = 0; k < 3; ++k) std::cout << M.at<double>(i, j * 3 + k) << std::endl;
这种方式需要手动计算每个通道在内存中的位置,可读性较差,不推荐。
方式三:使用指针直接访问
对于性能要求较高的场景,也可以用ptr方法获取行指针,直接遍历内存:
for (int i = 0; i < M.rows; ++i) { double* row = M.ptr<double>(i); for (int j = 0; j < M.cols; ++j) { for (int k = 0; k < 3; ++k) { std::cout << row[j * 3 + k] << std::endl; } } }
内容的提问来源于Stack Exchange,提问作者Display Name
相关产品推荐
相关产品推荐

