我知道有几种方法可以读取和写入OpenCV cv::Mat
图像/矩阵的像素值。
常见的是.at<typename T>(int, int)
方法http://opencv.itseez.com/2.4/modules/core/doc/basic_structures.html#mat-at。
但是,这需要知道typename,例如.at<double>
。
同样的事情适用于更直接的指针访问OpenCV get pixel channel value from Mat image。
如何在不知道其类型的情况下读取像素值?例如,可以接收更通用的CvScalar
值作为回报。效率不是问题,因为我想阅读相当小的矩阵。
答案 0 :(得分:3)
有点儿。您可以构造cv::Mat_
并为元素提供显式类型,之后您不必每次都编写元素类型。引用opencv2/core/mat.hpp
虽然在大多数情况下Mat足够,但如果使用大量元素,Mat_会更方便 访问操作,如果您在编译时知道矩阵类型。注意
Mat::at(int y,int x)
和Mat_::operator()(int y,int x)
完全相同 并且以相同的速度运行,但后者肯定更短。
Mat_
和Mat
非常相似。再次引用mat.hpp:
类
Mat_<_Tp>
是Mat类之上的 thin 模板包装器。它没有任何 额外的数据字段。这类和Mat也没有任何虚拟方法。因此,引用或指向 这两个类可以自由但小心地相互转换。
您可以像这样使用
Mat_<Vec3b> dummy(3,3);
dummy(1, 2)[0] = 10;
dummy(1, 2)[1] = 20;
dummy(1, 2)[2] = 30;
cout << dummy(1, 2) << endl;
为什么我首先说'有点'?因为如果你想在某个地方传递这个Mat_ - 你必须指定它的类型。像这样:
void test(Mat_<Vec3b>& arr) {
arr(1, 2)[0] = 10;
arr(1, 2)[1] = 20;
arr(1, 2)[2] = 30;
cout << arr(1, 2) << endl;
}
...
Mat_<Vec3b> dummy(3,3);
test(dummy);
从技术上讲,你没有在像素读取期间指定你的类型,但实际上你仍然必须知道它并事先将Mat转换为适当的类型。
我想你可以使用一些低级别的黑客来找到解决方法(比如制作一个读取Mat类型的方法,计算元素大小和步幅,然后使用指针算法和转换来访问原始数据......)。但我不知道使用OpenCV功能的任何“干净”方式。
答案 1 :(得分:2)
如果您已经知道类型,则可以使用Mat_<>
类型轻松访问。如果您不知道类型,可以:
double
,因此无论如何都不会截断数据Scalar
最多包含4个元素。以下代码仅将源矩阵的选定元素转换为double值(使用N
个通道)。
您获得的Scalar
包含源矩阵中位置row
,col
的值。
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace std;
using namespace cv;
Scalar valueAt(const Mat& src, int row, int col)
{
Mat dst;;
src(Rect(col, row, 1, 1)).convertTo(dst, CV_64F);
switch (dst.channels())
{
case 1: return dst.at<double>(0);
case 2: return dst.at<Vec2d>(0);
case 3: return dst.at<Vec3d>(0);
case 4: return dst.at<Vec4d>(0);
}
return Scalar();
}
int main()
{
Mat m(3, 3, CV_32FC3); // You can use any type here
randu(m, Scalar(0, 0, 0, 0), Scalar(256, 256, 256, 256));
Scalar val = valueAt(m, 1, 2);
cout << val << endl;
return 0;
}