cv::Vec类
cv::Vec<>
是固定向量类,不同与STL的vector是动态向量,更像是STL的array,长度固定;如cv::Vec
;
有已经内置的别名:cv::Vec{2,3,4,6}{b,w,s,i,f,d}
cv::Vec{2,3,4,6}{b,w,s,i,f,d}
//内置的类型重命名:typedef Vec Vec3b
//b unsigned char 常用
//i int 常用
//f float 常用
//w unsigned short
//s short
//d double
声明格式如下:
cv::Vec<float,3> vec1;
cv::Vec3b vec2; //默认构造函数
cv::Vec3f vec3(vec4); //拷贝构造
cv::Vec3f vec3(x0,x1,x2); //值构造
//*********************成员访问,下标,和C++的数组很像
vec3[i];vec3(i)//中括号,小括号都可以,都被重载了
vec3.cross(vec4); //叉乘
cv::Point类
二维或者三维点
cv::Point
类不是从cv::Vec
继承过来的,它访问成员不是用下标,而是.x
, .y
访问,也有如下别名:分别对应二维和三维的整型和浮点型的点
cv::Point2i, cv::Point2f, cv::Point2d, cv::Point3i, cv::Point3f, cv::Point3d
cv::Point3i p1; //默认构造函数
cv::Point3i p2(p1); //拷贝构造函数
cv::Point3i p3(x0,x1,x2); //值构造函数
//******************************
int x=p3.x, y=p3.y, z=p3.z; //成员的访问,类似是个结构对象
float x=p2.dot(p3); //点乘
p1.cross(p2) //叉乘,三维的才有,二维没有
p.inside(r); //点在矩形内
cv::Scalar类
,四维点,四元数,元素都是double型
cv::Scalar s; //默认构造函数
cv::Scalar s2(s1); //拷贝构造函数
cv::Scalar s(x0,x1,x2,x3); //值构造函数
s1.mul(s2); //元素相乘
s.conj(); //共轭(return cv::Scalar(x0,-x1,-x2,-x3))
s.isReal(); //(return true, if s1==s2==s3==0)
cv::Size类
二维的数,表示矩阵的尺寸嘛,肯定长和宽啦,和Point类似不是用下标取值,是用.width
, .height
cv::Size sz;//默认构造函数 和Size2i一样
cv::Size2i sz;
cv::Size2f sz;
cv::Size sz2(sz); //拷贝构造函数
cv::Size sz(w,h); //值构造函数
//*****************************
sz.width; sz.height ///访问成员
sz.area(); //return sz.width*sz.height
cv::Rect类
矩形类,包含Point(左上角)和Size(尺寸)
cv::Rect r; //默认构造函数
cv::Rect r2(r1); //拷贝构造
cv::Rect r2(x,y,w,h); //值构造
cv::Rect r(p,sz); //Point和Size
cv::Rect r(p1,p2); //两个Point
//**********************访问成员
r.x; r.y; r.width; r.height; //来自Point的x,y,来自Size的width,hwight
r.area(); //面积
r.tl(); //左上角
r.br(); //右下角
r.contains(p); //判断点在矩形内
RotatedRect类
带旋转角度的矩形,不常用
cv::Matx类
cv::Matx<>
固定矩阵类,用于小型矩阵,如22,33;如cv::Matx<5,5,float>
,注意,竟然是尺寸在前,类型在后,和Vec不一样; 也有别名cv::Matx{1,2,3,4,6}{1,2,3,4,6}{f,d}
, 因为是固定尺寸,所以效率比cv::Mat
高;
当提前就知道矩阵尺寸的时候,就用cv::Matx,不知道尺寸的大型矩阵,再用cv::Mat
cv::Matx34f m34f; //默认构造函数
cv::Matx22d m22d(n22d); //拷贝构造
cv::Matx33d m33d(x0,x1,x2,x3,x4,x5,x6,x7,x8); //值构造
cv::Matx33f m33f=cv::Matx33f::all(x); //元素一样的矩阵,类的静态成员函数
cv::Matx33f m33f=cv::Matx33f::zeros(); //元素全为0
cv::Matx33f m33f=cv::Matx33f::ones(); //元素全为1
cv::Matx33f m33f=cv::Matx33f::eye(); //单位矩阵
//************************成员访问
m33f(i,j),m31f(i); //用小括号,不是下标,在C++少见
m91f=m33f.reshape<9,1>(); //reshape
//**********************************************/
m41f=m44f.row(i); //**********第i行
m41f=m44f.col(j); //********第j列
m44f.diag(); //取对角
m44f.t(); //*****************转置******
m44f.inv(); //************求逆*********
m1.mul(m2); //每个元素乘
cv::Mat类
OpenCV的C++实现的核心,几乎所有函数都是:cv::Mat的成员,或者将cv::Mat作为参数,或者返回一个cv::Mat类型;
cv::Mat
用于表示任意维度的稠密数组。OpenCV中图像的存储方式就是cv::Mat大型矩阵,有单通道或者三通道等等。
cv::Mat中的元素可以是一个数字,也可以包含多个数字,此时是“多通道数组”。
数据类型:CV_{8U,16S,16U,32S,32F,64F}C{1,2,3}
。比如CV_32FC3表示三通道的32位浮点数;CV_8UC3常用.
cv::Mat m;//默认构造函数,没有指明存储数据类型和矩阵大小
m.create(3,10,CV_32FC3); //.create()成员函数,指定行数,列数,数据类型
//常用
cv::Mat m(int rows, int cols, int type);
// cv::Mat(rows,cols,type,初始化);
cv::Mat m(3,4,CV_32FC3,cv::Scalar(0,1,2)); //每个数据元素的三通道都是[1,2,3]
//则 m.at(2,3) = [1,2,3]
cv::Mat m(cv::Size sz, int type); //Size是宽cols,高rows
cv::Mat m(cv::Size(640,480),CV_8UC1);
//有时候初始化小型矩阵 类型是CV_32FC1,4行2列
cv::Mat mat = (cv::Mat_<float>(4,2)<<0,1,2,3,4,5,6,7);
// 注意****************是浅拷贝,只是指针指向m1;修改了m2则m1也变了
cv::Mat m(const Mat& mat); //复制构造*******浅复制
cv::Mat m2(m1);
//或者
cv::Mat m2=m1;
//*******************************************************
cv::Mat m = cv::Mat::zeros(rows,cols,type);
cv::Mat m = cv::Mat::ones(rows,cols,type);
cv::Mat m = cv::Mat::eye(rows,cols,type);
// 访问数据 .at<>(,)
cv::Mat m=cv::Mat::eye(10,10,32FC1);
m.at<float>(3,3);
cv::Mat m1=cv::Mat::eye(10,10,32FC3);
m1.at<cv::Vec3f>(3,3); //是个cv::Vec3f
m1.at<cv::Vec3f>(3,3)[0];
m1.at<cv::Vec3f>(3,3)[1];
m1.at<cv::Vec3f>(3,3)[2];
// 访问数据,迭代器
cv::MatIterator_<float> it=m.begin<float>(); //*it
auto it=m.end<float>();
//访问图像第row行,第col列,第c通道的数据
image.at<Vec3b>(row,col)[c] //前提得知道: 3通道,unsigned char
image.data[row*image.step + col*image.channels() + c] //image.step 一行占用的最小元素个数
访问区块(也都是浅拷贝,只是指针指向了那里)
cv::Mat m(10,20,CV_8UC1,0);
m.row(i); //第i行
m.col(j); //第j列
m.rowRange(i0,i1); //i0到i1-1行
m.colRange(j0,j1); //j0到j1-1列
m.diag(d);//偏移为d的对角元素数组
m(cv::Range(i0,i1),cv::Range(j0,j1)); //矩阵内的数组
m(cv::Rect(i0,i1,w,h)); 矩阵内的,起点,长高
cv::Mat的运算操作
m1+m2; m1-m2; //矩阵加减法,矩阵尺寸要一样
m1+num; m1-num; //矩阵加减单个数
num*m1; //矩阵乘以一个数
m1.mul(m1); //两个矩阵按元素相乘
m1*m2; //矩阵乘法
m1.inv();//对矩阵求逆
m1.t(); //转置
m1>m2; //按元素比较,返回值只有0或255
m1&m2; m1|m2; ~m1;//与或非
min(m1,m2);max(m1,m2); //按元素
cv::abs(m1);//绝对值
cv::norm();
cv::mean();
cv::sum();
//等等
深拷贝
m2=m1是浅拷贝,m2只是数组头,指向m1,同一个数据,修改m2影响m1;
深拷贝如下:
//两个一样,用第一个就好
m2=m1.clone();
m1.copyTo(m2);
.reshape(channel, row) 通道数:0表示不变, 行数:0表示不变
cv::Mat m1(2,50,CV_8UC1,1);
cv::Mat m2=m1.reshape(0,10); //通道数不变,尺寸变成10*10
1、对cv::Mat操作,获取值,赋值; 1、位置.at<>()
;2、迭代器cv::MatIterator_<>
.begin<>() .end<>()
#include
#include
using namespace std;
int main(int argc,char** argv)
{
cv::namedWindow("Window1",cv::WINDOW_AUTOSIZE);
cv::Mat m1(3,4,CV_8UC3,cv::Scalar(1,2,3)); //三行四列,三通道八位unsigned char,都初始化为[1,2,3]
cout<<"channels = "<<m1.channels()<<endl; //通道数:3
cout<<"size = "<<m1.size()<<endl; //size: 4*3 是宽和高,不是行和列
cout<<"width = "<<m1.cols<<endl<<"height = "<<m1.rows<<endl; //rows:3 cols:4
cout<<"m1.at(2,3) = " <<m1.at<cv::Vec3f>(2,3)<<endl;
cv::Mat m2(4,4,CV_8UC1,8); //四行四列,单通道八位unsigned char, 都初始化为8
cout<<"m2 = "<<endl<<m2<<endl;
cv::Size sz=m2.size(); //sz=[4 * 4]
int num=sz.area(); //16
//用.at<>()获取每个元素,修改每个元素
for(int i=0;i<num;i++)
m2.at<uchar>(i)=i+1;
cout<<"m2 = "<<endl<<m2<<endl;
//用迭代器cv::MatIterator_<> 获取每个元素,修改每个元素
cv::MatIterator_<uchar> it=m2.begin<uchar>();
int i=16;
for(;it!=m2.end<uchar>();it++)
{
*it=i;
i--;
}
cout<<"m2 = "<<endl<<m2<<endl;
return 0;
}
2、取cv::Mat数据块(范围)
#include
#include
using namespace std;
int main(int argc,char** argv)
{
cv::Mat m(10,20,CV_8UC1,(unsigned char)0);
cout<<"0 = "<<endl<<m<<endl;
int i=1;
for(auto it=m.begin<uchar>();it!=m.end<uchar>();it++) //迭代器赋值
{
*it=i;
i++;
}
cout<<"i = "<<endl<<m<<endl;
//单行,列
cout<<"m.row(2) = "<<endl<<m.row(2)<<endl;
cout<<"m.col(1) = "<<endl<<m.col(1).t()<<endl; //转置,不然是按列显示的
//行范围,列范围
cout<<"m.rowRange(1,3) = "<<endl<<m.rowRange(1,3)<<endl;
cout<<"m.colRange(1,3) = "<<endl<<m.colRange(1,3).t()<<endl;
//对角
cout<<"m.diag() = "<<endl<<m.diag()<<endl;
//矩形范围内,以下两个效果相同
cout<<"m(cv::Rect(1,1,5,5) = "<<endl<<m(cv::Rect(1,1,5,5))<<endl; //cv::Rect()矩形
cout<<"m(cv::Range(1,6),cv::Range(1,6) = "<<endl<<m(cv::Range(1,6),cv::Range(1,6))<<endl; //两个cv::Range()范围
return 0;
}
#运行结果
0 =
[ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0;
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
i =
[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20;
21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40;
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60;
61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80;
81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100;
101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115, 116, 117, 118, 119, 120;
121, 122, 123, 124, 125, 126, 127, 128, 129, 130, 131, 132, 133, 134, 135, 136, 137, 138, 139, 140;
141, 142, 143, 144, 145, 146, 147, 148, 149, 150, 151, 152, 153, 154, 155, 156, 157, 158, 159, 160;
161, 162, 163, 164, 165, 166, 167, 168, 169, 170, 171, 172, 173, 174, 175, 176, 177, 178, 179, 180;
181, 182, 183, 184, 185, 186, 187, 188, 189, 190, 191, 192, 193, 194, 195, 196, 197, 198, 199, 200]
m.row(2) =
[ 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
m.col(1) =
[ 2, 22, 42, 62, 82, 102, 122, 142, 162, 182]
m.rowRange(1,3) =
[ 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40;
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60]
m.colRange(1,3) =
[ 2, 22, 42, 62, 82, 102, 122, 142, 162, 182;
3, 23, 43, 63, 83, 103, 123, 143, 163, 183]
m.diag() =
[ 1, 22, 43, 64, 85, 106, 127, 148, 169, 190]
m(cv::Rect(1,1,5,5) =
[ 22, 23, 24, 25, 26;
42, 43, 44, 45, 46;
62, 63, 64, 65, 66;
82, 83, 84, 85, 86;
102, 103, 104, 105, 106]
m(cv::Range(1,6),cv::Range(1,6) =
[ 22, 23, 24, 25, 26;
42, 43, 44, 45, 46;
62, 63, 64, 65, 66;
82, 83, 84, 85, 86;
102, 103, 104, 105, 106]