前言
早期的 OpenCV 中,使用 IplImage 和 CvMat 数据结构来表示图像。 IplImage和 CvMat 都是 C 语言的结构。 使用这两个结构的问题是内存需要手动管理,开发者必须清楚的知道何时需要申请内存,何时需要释放内存。这个开发者带来了一定的负担,开发者应该将更多精力用于算法设计,因此在新版本的 OpenCV 中引入了 Mat 类。
1.关于mat类
1.1 Mat类成员:
属性:
Int flags;
Int dims;维数
Int rows,cols; 行列数
Uchar* data;数据指针
Int* refconut;引用次数
常用构造函数:
(1)只创建不初始化
Mat M(3,2,CV_8UC1);
(2)新创建Mat对象,并初始化
Mat M(3,2,CV_8UC3,Scalar(0,0,255));
Mat M(Sizesize,int type);
Mat M(Sizesize,int type,const Scalar& s);
(3)利用已有的对象(不会复制数据)
Mat::Mat(constMat& m)
Mat::Mat(constMat& m, const Rect& roi)
注:如果你需要更多的通道数,需要用宏CV_8UC(n),例如:
Mat M(3,2, CV_8UC(5));//创建行数为 3,列数为 2,通道数为 5 的图像
(4)用Mat::create()创建
(5)MATLAB风格创建特殊矩阵
Mat::zeros(rows,cols,type);
Mat::ones(rows,cols,type);Mat::eye(rows,cols,type);
注:Mat等类重载了<<运算符,cout<<M<<endl,打印矩阵元素;
1.2 Mat表达式
Mat a(),b(),c();
int k;
a=b+c;
c=a*k;
a.mul(b) 对应元素相乘
a/b,k/a对应元素除
a*b 矩阵乘
a.t() 转置
a.inv() 求逆
1.3.Mat_类
template<typename_Tp> class Mat_ : public Mat
{
public:
//只定义了几个方法
//没有定义新的属性
};
1.4 Mat内存管理
使用引用计数机制,当引用为0时,自动释放内存。
2.矩阵元素表达(多通道)
使用小向量VecNX,N表示通道数,
X = b(byte)
s(short)
i(int)
f(float)
d(double)
3.访问矩阵元素
3.1 at()
Mat M();
M.at<uchar>(i,j)
3.2 迭代器
3.3 指针
Matm(3,2,CV_8UC1);//sigle channel
For(inti=0;i<m.rows;i++)
{
Uchar* p = m.ptr<uchar>(i); //获取行指针
For(j=0;j<m.cols,;j++)
{
P[j] = xxx;
}
}
注意:这里的rows和cols的单位都是以矩阵元素为单位的
Matm(3,2,CV_8UC3);//three channels
For(int=0;i<m.rows;i++)
{
Vec3b* pv = m.ptr<Vec3b>(i);
For(int j=0;j<cols;j++)
{
Pv[j][0] = aaa;
Pv[j][2] = aaa;
Pv[j][3] = aaa;
}
}
注意:Data* p; p[i]是以Data数据项为单位计数的。
4.IplImage,CvMat与Mat转换
这块用到再补充。
5.读写图像
Mat imread(conststring& filename,int flags=1);
Flags>0 强制转换成3channel
Flags=0强制转换成1channel
Flags<0 不转换
bool imwrite(conststring& filename,
InputArray image,
Vector<int>& params);
Vector<int>¶ms 与图像格式有关的参数。
注意:并不是所用类型的Mat都能够被保存为图像。有的需要进行转换才可以。
6.读取视频(VideoCapture)
(1)创建VideoCapture对象
VideoCapture cap(“xxx.avi”);
(2)加载一帧图像到内存
Mat frame;
cap>>frame;
(3)显示图像
imshow(“windowName”,frame);