如何通过像素索引从cv::Mat中获取对应像素的cv::Point?
问题原因分析
你遇到的崩溃本质是两个核心误解:
cv::Mat::at<T>(index)的用法逻辑:当你传入单个整数索引时,是把Mat当作一维连续数组来访问,但要求模板类型T的字节大小必须和Mat的elemSize()(每个像素元素的字节数)完全匹配。你的彩色图像是CV_8UC3类型,每个元素是cv::Vec3b(3字节),所以at<Vec3b>(index)能正常运行;但cv::Point(通常是两个int,8字节)和elemSize()=3不匹配,触发了断言检查失败。- 像素存储逻辑:你的
src是彩色图像Mat,它存储的是像素的颜色值,而不是cv::Point类型的坐标数据。cv::Point是用来表示像素的位置(x,y),并非Mat中实际存储的内容,所以你根本不可能直接从Mat里读取到cv::Point对象。
正确实现方案
要通过线性索引获取对应像素的cv::Point坐标,你需要把线性索引转换为二维的行(y)和列(x),再构造cv::Point。转换公式很简单:
- 线性索引
idx = y * cols + x - 反过来推导:
y = idx / cols,x = idx % cols(这里的cols是Mat的列数)
修改后的代码如下:
cv::Mat src = imread(image_path, cv::IMREAD_COLOR); if (src.empty()) { // 记得加图像读取失败的判断,避免后续出错 std::cerr << "Failed to read image!" << std::endl; return -1; } int max_index = src.size().area(); // 获取总像素数 // 输出最后一个像素的颜色,运行正常 std::cout << src.at<cv::Vec3b>(max_index - 1) << std::endl; // 转换线性索引为cv::Point坐标 int cols = src.cols; int target_idx = max_index - 1; int y = target_idx / cols; int x = target_idx % cols; cv::Point pixel_pos(x, y); // 输出最后一个像素的点信息 std::cout << pixel_pos << std::endl;
额外说明
如果你的场景是需要存储cv::Point类型的数据集(比如特征点坐标),需要创建专门的Mat类型,比如:
// 创建存储Point2i的Mat,行数1,列数5,元素类型为CV_32SC2 cv::Mat point_mat(1, 5, CV_32SC2); // 此时可以直接用at<cv::Point>访问 point_mat.at<cv::Point>(0) = cv::Point(10,20); std::cout << point_mat.at<cv::Point>(0) << std::endl;
但回到你的问题,彩色图像Mat并不存储坐标点,所以必须通过索引转换来得到cv::Point。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

