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);
查表运算是最快的运算方式
查表对于图像转换,可以直接使用