OpenCV—数据结构与基本绘图(一)

简介: OpenCV—数据结构与基本绘图(一)

第4章:OpenCV数据结构与基本绘图

一、基础图像容器Mat

1、数字图像存储概述

我们通过显示屏看到的图像是由数字设备记录的图像中的每个点的数值。

2、Mat结构的使用

(1)优点:

  • 不必要再动手为其开辟空间
  • 不必再不需要时立马将空间释放

(2)Mat简介:

Mat是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储所有像素值的矩阵的指针。矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。所以,创建图像副本时,大的开销时由矩阵造成的,而不是信息头。


为了解决以上开销大的问题,OpenCV使用了引用计数机制:让每个Mat对象有自己的信息头,通过矩阵指针指向同一地址,让它们共享一个矩阵。

Mat A,C;//仅创建信息头部分
A=imread("1.jpg",CV_LOAD_IMAGE_COLOR);//为矩阵开辟内存
Mat B(A);//使用拷贝构造函数
C=A;//赋值运算符

以上代码中的所有Mat对象最终都指向同一个也是唯一一个数据矩阵。

附加:

  • 可以创建只引用部分数据的信息头
Mat D (A,Rect(10,10,100,100));//使用矩形界定
Mat E=A(Range:all(),Range(1,3));//用行和列界定
  • 若是矩阵属于多个Mat对象,通过引用计数机制来实现,复制一次Mat对象的信息头,增加一次引用次数。当一个头释放后,计数减一;计数为0时,矩阵就会被清理。
  • 此时若想复制矩阵本身(不只是信息头和矩阵指针)
Mat A;
//Mat F = A.clone();
Mat F;
A.copyTo(F);

(3)补充:上面(1)和(2)的内容是书上讲的,新手小白看的不是很懂,可以去b站了解一下。

3、像素值的存储方法

说明:存储像素值需要指定颜色空间和数据类型。颜色系统如下:

  • RGB颜色空间是最常用的一种颜色空间,他的基色是红色、绿色和蓝色,表示透明的颜色也会加入第四个颜色alpha
  • HSV和HLS把颜色分解成色调、饱和度和亮度。

每个组成元素都有自己的定义域,而定义域取决于其数据类型。符号型(0-255)和无符号型(-127-127)

4、显示创建Mat对象的七种方法(初始化)

(1)使用Mat()构造函数

Mat M(2,2,CV_8UC3,Scalar(0,0,255));
cout<<"M= "<<endl<<" "<<M<<endl<<endl;

CV_[位数] [带符合与否] [类型前缀] C[通道数] :

如:CV_8UC3:表示8位的unsigned char型,每个像素由三个元素组成的三通道。

(2)在C/C++中通过构造函数进行初始化

下面代码讲述如何创建一个超过两维的矩阵:指定维数,然后传递一个指向一个数组的指针,这个数组包含每个维度的尺寸,后面两个参数与(1)方法一致。

int sz[3]={2,2,2};
Mat L(3,sz,CV_8UC,Scalar::all(0));

说明:Scalar是一个short型的向量,能使用指定的定制化值来初始化矩阵,还可以用于表示颜色。

(3)为已经存在的IplImage指针创建信息头

IplImage* img=cvLoadImage("12.jpg",1);
Mat mtx(img);//转化IplImage*->Mat

(4)利用Create()函数

说明:利用Mat类中的Create()成员函数进行Mat类的初始化操作

M.create(4,4,CV_8UC(2));
printf("M= \n");
cout << m << endl<<endl;

(5)采用Matlab式的初始化方式

说明:采用Matlab形式的初始化方式:zeros(),ones(),eyes()。

Mat E=Mat::eye(4,4,CV_64F);
cout<<"E = "<<endl<<" "<<E<<endl<<endl;

Mat O=Mat::ones(2,2,CV_32F);
cout<<"O = "<<endl<<" "<<O<<endl<<endl;

Mat Z=Mat::zeros(3,3,CV_8UC1);
cout<<"Z = "<<endl<<" "<<Z<<endl<<endl;

(6)对小矩阵使用逗号分隔符初始化函数

Mat C=(Mat_<double>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
cout<<"C= "<<endl<<" "<<C<<endl<<endl;

(7)为已存在的对象创建新信息头

说明:使用成员函数clone()或者copyTo()为一个已经存在的Mat对象创建一个新的信息头

Mat RowClone=C.row(1).clone();
cout<<"RowClone= "<<endl<<" "<<RowClone<<endl<<endl;

5、OpenCV中的格式化输出方式

首先对于r矩阵的定义,通过randu()函数产生的随机值来填充矩阵,定一个上下限来确保随机值在期望范围内:

Mat r = Mat(10,3,CV_8UC3);//10代表10行,3表示几个通道;后面3表示每个通道数量
randu(r,Scalar::all(0),Scalar::all(255));

(1)OpenCV默认

cout<<"r(opencv默认) = "<<r<<";"<<endl<<endl;

(2)python风格

cout<<"r(python)风格= "<<format(r,Formatter::FMT_PYTHON)<<";"<<endl<<endl;

(3)逗号分隔风格(CSV)

cout<<"r(逗号分隔风格)= "<<format(r,Formatter::FMT_CSV )<<";"<<endl<<endl;
//format格式化

(4)Numpy风格

cout<<"r(Numpy风格)= "<<format(r,Formatter::FMT_NUMPY )<<";"<<endl<<endl;
//format格式化

(5)C语言风格

cout<<"r(C风格)= "<<format(r,Formatter::FMT_C )<<";"<<endl<<endl;

6、输出其他常用的数据结构

(1)定义和输出二维点

Point2f p(6,2);
cout<<"【二维点】p= "<<p<<";"<<endl;

(2)定义和输出三维点

Point3f p(6,2,0);
cout<<"【三维点】p3f= "<<p3f<<";\n"<<endl;

(3)定义和输出基于Mat的std::vector(vector是一个能够存放任意类型的动态数组,能够增加和压缩数据.)

vector<float> v;
v.push_back(3);
v.push_back(5);
v.push_back(7);
cout<<"【基于Mat的vector】shortvec= "<<Mat(v)<<";\n"<<endl;

(4)定义和输出std::vector点(以存放Point2f为例)

vector<Point2f>point(20);
for(size_t i=0;i<points.size();i++){
    points[i]=Point2f((float)(i*5),(float)(i%7));
    cout<<"【二维点向量】points = "<<points<<";"<<endl;
}

相关文章
|
7月前
|
C++
OpenCV-绘制简易直方图DrawHistImg
OpenCV-绘制简易直方图DrawHistImg
|
13天前
|
存储 计算机视觉
OpenCV—学习基本绘图
OpenCV—学习基本绘图
|
5月前
|
算法 计算机视觉 开发者
OpenCV图形检测中绘制图像的轮廓讲解与实战应用(附Python源码)
OpenCV图形检测中绘制图像的轮廓讲解与实战应用(附Python源码)
77 0
|
5月前
|
计算机视觉
opencv基础图形的绘制
opencv基础图形的绘制
27 0
|
5月前
|
计算机视觉
[QT5&OpenCV] 边缘检测、轮廓提取及轮廓跟踪
[QT5&OpenCV] 边缘检测、轮廓提取及轮廓跟踪
118 0
|
7月前
OpenCV-绘制同心圆
OpenCV-绘制同心圆
|
7月前
OpenCV-绘制多边形(fillConvexPoly和fillPoly的区别)
OpenCV-绘制多边形(fillConvexPoly和fillPoly的区别)
120 1
|
7月前
OpenCV-绘制圆端矩形(药丸)
OpenCV-绘制圆端矩形(药丸)
OpenCV-绘制圆端矩形(药丸)
|
7月前
OpenCV-绘制圆角矩形
OpenCV-绘制圆角矩形
|
7月前
|
计算机视觉
OpenCV-绘制箭头cv::arrowedLine
OpenCV-绘制箭头cv::arrowedLine