1.分类
基本数据结构(basic data types)
辅助数据结构(Helper object)
大型数据结构(Large array object):mat
STL数据结构:vector,pair
2.基础数据结构:Point、Scalar、Size、cv::Rect、RotatedRect、Matx
3.点Point
3.1Point构造
cv::Point2i p; //定义点p为2位的整形,例如(x,y) x和y取整形数据
cv::Point3f p; //定义点p为3位的浮点型,例如(a,b,c),abc取float数据
cv::Point3f p2(p1); //拷贝构造,将p1拷贝给p2
cv::Point2i p(x0,x1); //赋值构造,x0和x1直接取int型数据
cv::Point3d p(x0,x1,x2); //赋值构造,x0,x1,x2直接取double类型数据
3.2Point取值
int i=p.x; //取Point2i的x坐标
float f=p.y; //Point2f的y坐标
3.3Point函数
p.inside(r); //判断p是否在r中
cv::Point2i p=Point2i(10,10);
cv::Point2i p1=Point2i(200,200);
cv::Recti2i r=Rect2i(0,0,100,100);
bool b=p.inside(r);
bool b1=p1.inside(r);
4. 4位double类型Scalar:n.数量,标量
cv::Scalar是四位双浮点数的点集合 4位double
Scalar(255)表示全白,Scalar(g,b,r)表示一个GBR色彩只是它功能的一种
4.1Scalar构造
cv::Scalar s; //空构造
cv::Scalar s2(s1); //拷贝构造 将s1赋值给s2
cv::Scalar s(x0); //赋值构造
cv::Scalar s(x0,x1,x2,x3); //赋值构造
4.2Scalar函数
s1.mul(s2); //乘法 每一位分别相乘
Scalar s(255,255,255);
Scalar s2(10,100,255);
Scalar ss=s.mul(s2);
5.尺寸Size
5.1Size构造
cv::Size sz; //空构造
cv::Size2i sz; //2位int型
cv::Size2f sz; //2位float型
cv::Size sz2(sz1); //将sz1拷贝给sz2
cv::Size2f sz(w,h); //赋值构造,w和h分别对应属性width和height
5.2取值
sz.width; //取宽度
sz.height; //取高度
size不能够和老的数据结构相互转换。
6.平行矩形Rect
6.1Rect构造
cv::Rect r; //空构造
cv::Rect r2(r1); //拷贝构造,将r1赋值给r2
cv::Rect(x,y,w,h); //x,y左上角的点坐标 w,h矩形的宽高
cv::Rect(p,sz); //p指矩形左上角的点,sz的width和height就是矩形的宽高
cv::Rect(p1,p2); //p1指矩形左上角的点,p2指矩形右下角的点
Size size=Size(10,10);
cv::Rect r1(0,0,100,100);
cv::Rect r2(p,size);
cv::Rect r3(p,p2);
6.2Rect取值
r.x; //取左上角x坐标
r.y; //取左上角y坐标
r.width; //取矩形的宽度
r.height; //取矩形的高度
6.3Rect函数
r.area(); //面积
r.tl(); //左上点,top left
r.br(); //右下点,bottom right
r.contain(p); //r是否包含点p <==> p.inside(r); //p点是否存在于r内
6.4Rect几何运算
cv::Rect r3=r1&r2; //交运算
cv::Rect r3=r1|r2; //并运算
cv::Rect rs=r+s; //r偏移一个size
bool eq=(r1==r2); //判断r1、r2是否严格相等
7.旋转矩形RotatedRect
7.1RotatedRect构造
cv::RotatedRect rr(); //空构造
cv::RotatedRect rr2(rr1); //拷贝构造,将rr1赋值给rr2
cv::RotatedRect(p1,p2,p3); //赋值构造,p1,p2,p3必须是矩形的三个点,否则报错
cv::RotatedRect(p,sz,theta); //p为中心点,sz为sz,theta为角度 角度是0~360
cv::RotatedRect rr1=cv::RotatedRect(p,size,45);
7.2RotatedRect取值
rr.center; rr.size; rr.angle;
rr.points(pts(4)); //获得4个角点的值
Point2i p_rr=rr.center;
Size p_size=rr1.size;
float p_angle=rr1.rangle;
Point2f pts[4]; //点的数组,长度是4,数据类型为float
rr.points(pts); //执行完之后,pts内四个点就是矩形rr1的四个角点
8.矩阵Matrax
Mat可以任意维的,Matx是确定维数的。 特点:quick
8.1Matx构造
cv::Matx33f m33f; cv::Matx43d m43d; //空构造
cv::Matx22d m22d(n22d); //拷贝构造
Matx33f m(1,2,3
4,5,6
7,8,9); //赋值构造
cv::Matx m33f=cv::Matx33f::all(x); //eg:x=6,三行三列全部都是6
cv:Matx m23d=cv::Matx23d::zeros(); //6个0
cv::Matx m16f=cv::Matx16f::ones(); //ones是全是1的意思
cv::Matx m33f=cv::Matx33f::eye(); //单位矩阵的意思。(1,0,0
0,1,0
0,0,1)
8.2Matx取值
m(i,j); m(i); //取值
double d23=m23d(1,2); //第2行第3列
float f16=m16f(0,0); //第1行第1列
Matx13f m13f=m33f.row(2); //第3行
Matx31f m31f=m33f.col(2); //第3列
8.3Matx基本计算
m1=m0; //赋值
m0*m1; //相乘
m0+m1; //相加
m0-m1; //相见
m*a; //矩阵乘以一个常数
a*m; //一个常数乘以一个矩阵
m/a; //矩阵除以一个常数,a不等于0
8.4Matx操作计算
n44f=m44f.t(); //转置
标量乘与点乘要求相乘的两个矩阵结构必须是一样的,标量乘必须是一维的。
m1.mul(m2); //点乘
标量乘 (a1,a2,a3,a4)*(b1,b2,b3,b4)=a1*b1+a2*b2+a3*b3+a4*b4;
向量乘可以3*3与3*1. 向量乘用的符号*
向量乘 (a00,a01 (b00,b01,b02 (a00*b00+a01*b10,a00*b01+a01*b11,a00*b02+a01*b12
a10,a11 * b10,b11,b12) = a10*b00+a11*b10,a10*b01+a11*b11,a10*b02+a11*b12
a20,a21) a20*b00+a21*b10,a20*b01+a21*b11,a20*b02+a21*b12)
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace cv; //opencv引用 5 using namespace std; //C++标准库函数 6 7 int main(int argc, char** argv[]) 8 { 9 //图片数据 10 Mat src = imread("F:/OpenCV/模拟图像/002.jpg"); //不加读取参数,默认彩色图像 11 imshow("src", src); 12 //points 13 cv::Point2i p = Point2i(10, 10); 14 cv::Point2i p2 = Point2i(200, 200); 15 cv::Point2f p1 = Point2f(0, 0); 16 cv::Point2f p3 = Point2f(10, 10); 17 cv::Point2f p4 = Point2f(200, 200); 18 cv::Rect2i r = Rect2i(0, 0, 100, 100); 19 bool b = p.inside(r); //判断点是否在矩形中 20 bool b2 = p2.inside(r); 21 //scalar 22 Scalar s(255, 255, 255); 23 Scalar s2(10, 100, 255); 24 Scalar ss; 25 ss = s.mul(s2); 26 //rect 27 Size size = Size(100, 100); 28 cv::Rect r1(0, 0, 100, 100); //赋值构造 29 cv::Rect r2(p, size); 30 cv::Rect r3(p, p2); 31 Size sos(10, 10); 32 cv::Rect r4 = r1 & r2; 33 bool eq = (r1 == r2); //这里的是否相等是严格的相等,不仅仅是面积 34 //rotatedrect 35 Point2f pf1 = Point2f(0, 0); 36 Point2f pf2 = Point2f(10, 0); 37 Point2f pf3 = Point2f(6, 10); 38 //cv::RotatedRect rr2 = cv::RotatedRect(pf1, pf2, pf3); 39 cv::RotatedRect rr1 = cv::RotatedRect(p, size, 45); // 创建数据结构 40 Point2i p_rr = rr1.center; 41 Size p_size = rr1.size; 42 float p_angle = rr1.angle; 43 Point2f pts[4]; 44 rr1.points(pts); 45 //matx 46 Matx33f m(1, 2, 3, 47 4, 5, 6, 48 7, 8, 9); 49 cv::Matx23d m23d = cv::Matx23d::zeros(); 50 cv::Matx16f m16f = cv::Matx16f::ones(); 51 cv::Matx33f m33f = cv::Matx33f::eye(); 52 cv::Matx33f randu33f = cv::Matx33f::randu(0, 1); 53 double d23 = m23d(1, 2); 54 float f16 = m16f(0, 0); 55 Matx13f m13f = m33f.row(2); 56 Matx31f m31f = m33f.col(2); 57 waitKey(); 58 return 0; 59 }
9.辅助数据结构:cv::Range cv::ptr cv::inputarray与cv::outputarray
标准类库数据结构:Std::vector Std::pairs
10.区域Rangle:一个连续的区域
11.1Rangle构造
cv::Rangle(int start,int end); //赋值构造
12.Rangle函数
size(); //大小 end-start
empty(); //是否为空
Mat src_half_down=src(Range(src.rows/2,src.rows),Rangle(0,src.cols));
Mat src_half_down2=src(Rect(0,src.row/2,src.cols,src.cols/2));
11.智能指针ptr
cv::ptr smart point:能够自动销毁(垃圾回收)
除了能能够在适当的时间自动删除指向的对象外,其工作机制类似于C++的内置指针
11.1ptr构造
cv::Ptr<Matx33f> p(new cv::Matx33f); //空构造 <>里放的是指针指向的数据结构 p为指针的实体 cv::Matx33f为内容的实体 p指向cv::Matx33f这个数据结构
cv::Ptr<Matx33f> p=makePtr<cv::Matx33f>(); //同上
11.2Ptr函数
empty(); //是否为空
release(); //释放,销毁
cv::Ptr<Matx33f> p(new cv::Matx33f);
bool b=p.empty(); //b=false
p.release();
b=p.empty(); //b=true
12.InputArray与OutputArray
包括cv::Scalar、cv::Vec、cv::Matx
一种通用模式
两者不同:InputArray一般被认为是const(readonly)常量
13.向量Vector
vector是一个十分有用的容器,可以理解成数组,数组里面可以放Mat,也可以嵌套
13.1Vector向量
Vector<类型> 变量名
std::vector<Mat> myVector;
std::vector<std::vector<cv::Point>> contours; //嵌套
13.2Vector函数
myVector.push_back(src); //尾部插入
Mat tmp=myVector[0]; //下标访问
vector<Mat>::iterator it; //使用迭代器访问
for(it=myVector.begin();it!=myVector.end();it++)
{
imshow("it",it);
}
myVector,insert(myVector.begin()+0,src_half_down); //在第i个元素前面添加
myVector.erase(myVector().begin()+1); //删除第i个元素
reverse(myVector.begin(),myVector.end()); //反转
sort(myVector.begin(),myVector.end(),comp); //排序
bool Comp(const Mat &a, const Mat &b)
{//重写了排序方法,按图片的高度从小打到排序
return a.rows < b.rows;
}
myVector.clear(); //清空
14.模板类型pair
哥俩好的意思,其中包含两个数据值(可以相同可以不同)
类似于键值对
14.1pair构造
pair<string,string> a; //空构造
pair<string,string> a("James","Joy"); //赋值构造
vector<pair<Mat,string>>
14.2取值
pair<string,string> a("Lily","Poly");
string name;
name=a.first;
name=a.second;
1 #include <opencv2/opencv.hpp> 2 #include <iostream> 3 4 using namespace std; 5 using namespace cv; 6 7 bool Comp(const Mat &a, const Mat &b) 8 { 9 return a.rows < b.rows; 10 } 11 12 int main(int argc, char** argv[]) 13 { 14 //图片数据 15 Mat src = imread("F:/OpenCV/模拟图像/002.jpg"); 16 imshow("src", src); 17 //range 18 cv::Range range = cv::Range(0, 4); 19 Mat src_half_down = src(Range(src.rows / 2, src.rows), Range(0, src.cols)); 20 //Mat src_half_down2 = src(Rect(0, src.rows / 2, src.cols, src.cols / 2)); 21 //ptr 22 cv::Ptr<Matx33f> p(new cv::Matx33f); //将声明的对象分配给指针 23 bool b = p.empty(); //b = false 24 p.release(); //释放销毁 25 b = p.empty(); //b = true 26 //vector 27 std::vector<Mat> myVector; 28 std::vector<std::vector<cv::Point>>contours; 29 myVector.push_back(src); //尾部插入 30 myVector.push_back(src_half_down); 31 Mat tmp = myVector[0]; //下标访问 32 vector<Mat>::iterator it; //使用迭代器访问 33 for (it = myVector.begin(); it != myVector.end(); it++) 34 { 35 imshow("it", *it); 36 } 37 myVector.insert(myVector.begin() + 0, src_half_down); //在第i个元素前面添加 38 39 reverse(myVector.begin(), myVector.end()); //翻转 40 sort(myVector.begin(), myVector.end(), Comp); //排序 41 42 myVector.erase(myVector.begin() + 1); //删除第i个元素 43 myVector.clear();//清空 44 //pair 45 pair<string, string> a("Lily", "Poly"); 46 string name; 47 name = a.first; 48 name = a.second; 49 50 waitKey(); 51 return 0; 52 }
15.大型数据结构:Mat(dense arrays)、SparseMat(sparse array)
16.Mat——OpenCV中最常用的数据结构
多维稠密数据结构 N-Dimensional Dense Arrays
稠密数据(从0、0到n、n每个位置都有数据)
稀疏数据(从0、0到n、n有的位置有数据,有的位置没数据)
Mat不仅仅用来表示图片
Mat本身是一个带有垃圾清理机制的数据结构(类),它指向了一块数据存储的区域,同时它的定义中还包括了其他一些信息。这些消息包括
类型type:UINT8
通道数channels:3
宽度width、高度height
数据data:像素数
步长stride
16.1Mat构造
cv::Mat; //空构造
cv::Mat(cv::Size sz,int type); //赋值构造
cv::Mat(cv::Size sz,int type,const Scalar&s); //赋值构造
cv::Mat mat=imread("path"); //图片从磁盘中读入内存,最常用
cv::Mat(const Mat& mat); //拷贝构造,由老结构中生生成
cv::Mat(const CvMat* old,bool copyData=false);
cv::Mat(consot IplImage* old,bool copyData=false);
三种特殊构造:
cv::Mat::zeros(rows,cols,type); //数据全0
cv::Mat::ones(rows,cols,type); //数据全1
cv::Mat::eye(rows,cols,type); //单位正,对角为1
如果是8位的,0代表全黑,255代表全白;如果是32位的,0代表全黑,1代表全白。
17.Mat图像遍历
遍历时要先初始化,指定结果图像Mat的尺寸和通道数
Mat可表示图像、数据和多维数组
17.1 at
at遍历图像的格式:M.at<float>(i,j,k); 如果是CV_8U类型,应该是<uchar>
1 //对色彩图像强度减半 2 for (int i = 0; i < src.rows; i++) 3 { 4 for (int j = 0; j < src.cols; j++) 5 { 6 //三通道图像[0][1][2] 7 //Vec3b:Vec<uchar, 3> Vec3b; 8 src.at<Vec3b>(i, j)[0] = src.at<Vec3b>(i, j)[0] / 2; 9 src.at<Vec3b>(i, j)[1] = src.at<Vec3b>(i, j)[1] / 2; 10 src.at<Vec3b>(i, j)[2] = src.at<Vec3b>(i, j)[2] / 2; 11 } 12 }
17.2 指针
opencv中图像Mat每一行数据元素之间在内存里是连续存储的额,但行与行之间可能有空白单元
指针遍历比at遍历速度要快
1 //图像遍历的第二种方式 指针方式 2 Mat outImage; 3 outImage.create(src.size(), src.type()); 4 int nr = src.rows; // 将3通道转换为1通道 5 int nl = src.cols*src.channels(); 6 for (int k = 0; k < nr; k++) 7 { 8 for (int i = 0; i < nl; i++) 9 { 10 outImage.ptr<uchar>(k)[i] = src.ptr<uchar>(k)[i] * 2; 11 } 12 }
17.3连续指针
连续指针比指针速度要快,但要求是图像每行在内存中必须是连续的
1 //图像便利的第三种方式 连续指针 2 nr = src.rows; 3 int nc = src.cols; 4 outImage.create(src.size(), src.type()); 5 if (src.isContinuous() && outImage.isContinuous()) 6 {//能否可以用连续指针,要事先判断图像存储是否是连续的 7 //类似于把n*n的图像拉成一行,拉成一长条 8 nr = 1; 9 nc = nc * src.rows*src.channels();//高*宽*通道 10 } 11 for (int i = 0; i < nr; i++) 12 { 13 const uchar* inData = src.ptr<uchar>(i); 14 uchar* outData = outImage.ptr<uchar>(i); 15 for (int j = 0; j < nc; j++) 16 { 17 *outData++ = *inData * 2; 18 } 19 }
17.4迭代器
也很常用
1 //图像遍历的第四种方式 迭代器 2 outImage.create(src.size(), src.type()); 3 //源数据都是用不可修改的迭代器变量 4 MatConstIterator_<Vec3b> it_in = src.begin<Vec3b>(); 5 MatConstIterator_<Vec3b> itend_in = src.end<Vec3b>(); 6 //输出使用可修改的迭代器变量 7 MatIterator_<Vec3b> it_out = outImage.begin<Vec3b>(); 8 MatIterator_<Vec3b> itend_out = outImage.end<Vec3b>(); 9 while (it_in != itend_in) 10 { 11 (*it_out)[0] = (*it_in)[0] * 2; 12 (*it_out)[1] = (*it_in)[1] * 2; 13 (*it_out)[2] = (*it_in)[2] * 2; 14 it_in++; 15 it_out++; 16 }
17.5 block方式
一次选择一行或一列
1 //图像遍历的第五种方式 BLOCK 2 Mat matRow = src.row(0); 3 Mat matCols = src.col(0); 4 Mat matRowRange = src.rowRange(0, 10); 5 Mat matSrcRange = src.colRange(0, 10); 6 Mat matDiag = src.diag(); //求特征矩阵 7 Mat roi = src(cv::Rect(0, 0, 10, 10)); //取ROI
18.Mat函数
m1=m0.clone(); //m0拷贝给m1
m0.copyTo(m1); //同上
m0.copyTo(m1,mask); //带有模板的拷贝
m0.convertTo(m1,type,scale,offset); //格式转换
Mat src32f; //注意量纲的变化
src.convertTo(src32,CV_32F,1.0/255); //8位转32,8位全白为255,32位全白为1,由255到1,量纲为1.0/255,注意不能是1/155,一个是浮点型,一个是整形
src32f.convertTo(src,CV_8U,255); //32位转8位,乘255
m0.setTo(s,mask); //带模板的设置
19.稀疏矩阵SparseMat
使用SparseMat,一方面是使用SparseMat带来的复杂和便利图像性能影响,一方面是由于减少了空运算而带来的性能提升。
19.1 SparseMat构造
cv::SparseMat sm; //空构造
cv::SparseMat sm(3,sz,CV_32F); //赋值构造,分别是维度、大小和类型
SparseMat sm(sm0); //拷贝构造,sm0可以是sparseMat,或者是Mat
19.2 SparseMat访问
智能指针:uchar* cv::SparseMat::ptr(int i0,bool createMissing,size_t* hashval=0);
i0,序号; createMissing,当创建对象为空的时候是否创建; Hashval,是否重新计算hash值
ref: SparseMat::ref<>()用来访问稀疏矩阵中的一个值
value: cv::SparseMat::value<>()的作用和用法与ref类似,但其返回的是const值,不能修改只能获得
find: cv::SparseMat::find<>()返回hash的值,而不是索引
1 //稀疏矩阵 2 int size[] = { 10,10 }; 3 cv::SparseMat sm(2, size, CV_32F); 4 for (int i = 0; i < 10; i++) { // Fill the array 5 int idx[2]; 6 idx[0] = size[0] * rand(); 7 idx[1] = size[1] * rand(); 8 sm.ref<float>(idx) += 1.0f; 9 } 10 // Print out the nonzero elements 11 cv::SparseMatConstIterator_<float> it = sm.begin<float>(); 12 cv::SparseMatConstIterator_<float> it_end = sm.end<float>(); 13 for (; it != it_end; ++it) { 14 const cv::SparseMat::Node* node = it.node(); 15 printf(" (%3d,%3d) %f\n", node->idx[0], node->idx[1], *it); 16 }
20.Mat基本函数
20.1取绝对值cv::abs()
cv::MatExpr cv::abs(cv::InputArray src);
cv::MatExpr cv::abs(const cv::MatExpr&src);
20.2得到两值差值的绝对值cv::absdiff
void cv::absdiff(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst);
dst=saturate(|src1-src2|);
20.3添加,将第2个图像添加到第一个图像中,并保存到输出结果中cv::add()
void cv::add(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst,cv::InputArray mask=cv::noArray(),int dtype=-1);
dst=saturate(src1+src2);
eg:cv::add(src,star,temp);
20.4弱化叠加操作cv::addWeighted()
void cv::addWeighted(cv::InputArray src1,double alpha,cv::InputArray src2,double beta,double gamma,cv::OutputArray dst,int dtype=-1);
dst=saturate(src1*α+src2*β+γ)
eg:cv::addWeighted(src,0.5,srcR,1,0,temp);
20.5取交集cv::bitwise_and()
void cv::bitwise_and(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst,cv::InputArray mask=cv::noArray);
dst=src1&src2;
20.6取并集cv::bitwise_or()
void cv::bitwise_or(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst,cv::InputArray mask=cv::noArray);
dst=src1|src2;
20.7取异或cv::bitwise_xor()
void cv::bitwise_and(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst,cv::InputArray mask=cv::noArray);
dst=src1^src2;
20.8取反cv::bitwise_not()
cv::bitwise_not(star,temp); //取反,黑的变白,白的变黑
20.9比较cv::compare()
bool cv::compare(cv::InputArray src1,cv::InputArray src2,cv::OutputArray dst,int cmpop);
flag: cv::CMP_EQ(src1==src2)
cv::CMP_GT(src1>src2)
cv::CMP_GE(src1>=src2)
cv::CMP_LT(src1<src2)
cv::CMP_LE(src1<=src2)
cv::CMP_NE(src1!=src2)
20.10极坐标cv::cartToPolar()
void cv::cartToPolar(cv::InputArray x,cv::InputArray y,cv::OutputArray magnitude,cv::OutputArray angle,bool angleIeInDegrees=false);
20.11cv::convertScaleAbs()
void cv::convertScaleAbs(cv::InputArray src,cv::OutputArray dst,double alpha=1.0.double beta=1.0);
dst=saturate|src*α+β|;
防止过曝
20.12非零值cv::countNonZero()
int cv::countNonZero(cv::InputArray mtx);
计算非零值
20.13颜色转换cv::cvtColor()
void cv::cvtColor(cv::InputArray src,cv::OutputArray dst,int code,int dstCn=0);
code:eg:RGB2GRAY、BGR2RGB
20.14图像转装cv::flip()
void cv::filp(cv::InputArray src,cv::OutputArray dst,int flipCode=0);
Code >0,y-filp =0,x-flip <0,both
20.15查表运算
void cv::LUT(cv::InputArray src,cv::InputArray lut,cv::OutputArray dst);
dst=lut(src);
查表运算是最快的运算方式
查表对于图像转换,可以直接使用