文章目录

  • 1.基础图像容器 Mat
    • 1.1Mat 结构的使用
    • 1.2像素值的存储方法
    • 1.3 显示创建 Mat 对象的七种方法
      • 1.3.1 Mat 的常用构造函数
    • 1.4 OpenCV 中的格式化输出方法
    • 1.5 输出其他常用数据结构
    • 1.6 取对角线元素
    • 1.7 Mat 表达式
    • 1.8 Mat 与 IplImage 和 CvMat 的转换
      • 1.8.1 Mat 转换为 IplImage 和 CvMat
      • 1.8.2 IplImage 和 CvMat 格式转为 Mat
  • 2 常用的数据结构和函数
    • 2.1 点的表示:Point 类
    • 2.2 颜色的表示:Scalar 类
    • 2.3 尺寸的表示:Size 类
    • 2.4 矩形的表示:Rect 类
    • 2.5 颜色空间转换:cvtColo()函数
    • 2.6 其他常用知识
  • 3.基本图形的绘制
    • 3.1 DrawEclipse() 函数的写法
    • 3.2 DrawFilledCircle() 函数的写法
    • 3.3 DrawPolygon() 函数的写法
    • 3.4 DrawLine() 函数的写法
    • 3.5 main 函数的写法

1.基础图像容器 Mat

1.1Mat 结构的使用

  Mat 是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸、存储方法,存储地址等信息)和一个指向所有像素值的矩阵(根据所选存储方法的不同,矩阵可以是不同的维数)的指针。矩阵头的尺寸是常数值,但矩阵本身的尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。因此在程序中传递图像并创建副本时,大的开销是由矩阵造成的,而不是信息头。
  为了解决开销问题,OpenCV 使用了引用计数机制。其思路是让每个 Mat 对象都拥有自己的信息头,但共享同一个矩阵。这通过让矩阵指针指向同一个地址实现。而拷贝构造函数则只复制信息头和矩阵指针,而不复制矩阵。

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

  我们可以创建只引用部分数据的信息头。比如想要创建一个感兴趣区域(ROI,region of interest),只需要创建包含边界信息的信息头:

 Mat D (A ,Rect(10, 10, 100));   //使用矩形界定Mat E = A(Range:all(), Range(1,3));    //用行和列界定

  对于矩阵的清理:通过引用计数机制来实现,我们无论什么时候复制一个 Mat 对象的信息头,都会增加矩阵的引用次数,反之,当一个头被释放后,这个计数被减一,当计数为零时,矩阵就会被清理。但某些时候想复制矩阵本身时(不是信息头和矩阵指针)。这时可以使用函数 clone() 或者 copyTo()。

 Mat F = A.clone();Mat G;A.copyTo(G);

  现在改变 F 或者 G就不会影响 Mat 信息头所指向的矩阵。
  可总结为以下四个要点:
  ● OpenCV 函数中输出图像的内存分配是自动完成的(如果不特别指定的话)。
  ● 使用 OpenCV 的 C++ 接口时不需要考虑内存释放的问题。
  ● 赋值运算符和拷贝构造函数(构造函数)只复制信息头。
  ● 使用函数 clone() 或者 copyTo() 来复制一幅图像的矩阵。

1.2像素值的存储方法

  存储像素值需要指定颜色空间和数据类型。颜色空间是指对于一个给定的颜色,如何组合颜色元素以对其编码。
  GRB 颜色空间是最常用的颜色空间,它的基色是红色、绿色和蓝色,有时为了表示透明颜色也会加入第四个元素 alpha(A)。
  颜色系统有很多,它们各有优势:
  ● GRB 是最常见的,这是因为人眼采用相似的工作机制,它也被显示设备所采用。
  ● HSV 和 HLS 把颜色分解成色调、饱和度和亮度/明度。这是描述颜色更自然的方式,比如可以通过抛弃最后一个元素,使算法对输入图像的光照条件不敏感。
  ● YCrCb 在 JPEG 图像格式中广泛使用。
  ● CIE Lab* 是一种在感知上均匀的颜色空间,它适合用来度量两个颜色之间的距离。
  每个组成元素都有自己的定义域,而定义域取决去其数据类型,如何存储一个元素决定了我们在其定义域上能控制的精度。最小的数据类型是 char ,占一个字节或者 8 位,可以是有符号型(0 ~ 255 之间)或是无符号型(-127 ~ +127)之间。尽管使用三个 char 类型元素已经可以表示 1600 万种颜色可能(使用 GBR 颜色空间),但若使用 float (4 字节,32 位)或 double 型(8 字节,64 位)则能给出更加精细的颜色分辨能力。

1.3 显示创建 Mat 对象的七种方法

  Mat 的 " << " 运算符也能将图片写入文件中,但该运算符只对二维矩阵有效。

方法一:使用 Mat 的构造函数:

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

运行结果:

  对于二维多通道图像,需要定义其尺寸,即行数和列数。然后,需要指定存储元素的数据类型以及每个矩阵的点通道数。为此,依以下规则有多种定义:
  CV_[位数][带符号与否][类型前缀]C[通道数]
  比如 CV_8UC3 表示使用 8 位的 unsigned char 型,每个像素由三个元素组成三通道。而预先定义的 通道数可以多达四个。另外,Scalar 是个 short 型的向量,能使用指定的定制化值来初始化矩阵,它还可以用于表示颜色。当然,若需要更多通道,可以使用大写的宏并把通道数放在小括号中,如方法二。

1.3.1 Mat 的常用构造函数

//1.无参构造函数
Mat::Mat()//2.创建行为 rows,列为 cols,类型为 type 的图像
Mat::Mat(int rows,int cols,int type)//3.创建大小为 size,类型为 type 的图像
Mat::Mat(Size size,int type)//4.创建行数为 rows,列数为 cols,类型为 type 的图像,并将所有元素初始化值为 s
Mat::Mat(int rows,int cols,int type,const Scalar& s)//5.创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s
Mat::Mat(Size size,int type,const Scalar& s)//6.将 m 赋值给新创建的对象,此处不会对图像数据进行复制,m 和新的图像共用图像数据
Mat::Mat(const Mat& m)/*7.创建行数为 rows,列数为 cols,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使
用 data 所指内存,图像的步长由 step 指定8*/
Mat::Mat(int rows,int cols,int type,void* data,size_t step = AUTO_STEP)//8.创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使
//用 data 所指内存,图像的步长由 step 指定
Mat::Mat(int rows,int cols,int type,void* data,size_t step = AUTO_STEP)/*9.创建的新图像为 m 的一部分,具体范围由 rowRange 和 colRange 指定,此构造函数也不进行图像数据
的复制操作,新图像与 m 共用图像数据。*/
Mat::Mat(const Mat& m,const Range& rowRange,const Range& colRange)/*10.创建的图像为 m 的一部分,具体的范围 roi 指定,此函数也不进行图像的复制,新图像与原图像共享
图像数据 */
Mat::Mat(const Mat& m,const Rect& roi)

方法二:在 C\C++ 中通过构造函数进行初始化

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

  上面的例子演示了如何创建一个超过两维的矩阵:指定维数,然后传递一个指向一个数组的指针,这个数组包含两个维度的尺寸,后续两个参数与方法一中的相同。

方法三:为已存在的 IplIamge 指针创建信息头
IplImage 的头文件为: #include<highgui/highgui_c.h>

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

方法四:利用 Create() 函数

 M.create(4, 4, CV_8UC(2));cout << "M = " << endl << " " << M << endl << endl;

运行结果:

  需要注意的是,此创建方法不能为矩阵设初值,只是在改变尺寸重新为矩阵开辟内存而已。

方法五:采用 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;

运行结果:

方法六:对小矩阵使用逗号分隔式初始化函数

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

运行结果:

方法七:为已存在的对象创建新信息头
  使用成员函数 copyTo() 或 clone() 为一个已存在的 Mat 对象创建一个新的信息头。

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

运行结果:

1.4 OpenCV 中的格式化输出方法

  先定义一个矩阵以供下列方法使用,可通过 randu() 函数产生的随机值来填充矩阵,需要给一个上限和下限来确保随机值在期望的范围内。

 Mat r = Mat(10, 3, CV_8UC3);randu(r, Scalar::all(0), Scalar::all(255));

风格一:OpenCV 默认风格

 cout << "r (OpenCV 默认风格) = " << endl << r << ";" << endl << endl;

结果图为:

风格二:Python 风格

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

结果图为:

风格三:逗号风格(CSV)

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

结果图为:

风格三:Numpy风格

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

结果图为:

风格三:C语言风格

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

结果图为:

1.5 输出其他常用数据结构

  1)定义和输出二维点

 Point2f p(6, 2);cout << "二维点 p" << p << ";\n" << endl;

运行结果:

  2)定义和输出三维点

 Point3f p3f(8, 2, 0);cout << "三维点 p3f" << p3f << ";\n" << endl;

运行结果:

  3)定义和输出基于 Mat 类的 std::vector

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

运行结果:

  4)定义和输出二维点
  定义和输出存放着点的 vector 容器,以存放二维点 Point2f 为例:

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

运行结果:

1.6 取对角线元素

  矩阵的对角线元素可以使用Mat类的diag()函数获取,该函数的定义如下:

Mat Mat::diag(int d) const

  参数d=0时,表示取主对角线;当参数d>0是,表示取主对角线下方的次对角线,如d=1时,表示取主对角线下方,且紧贴主多角线的元素;当参数d<0时,表示取主对角线上方的次对角线。
  如同row()和col()函数,diag()函数也不进行内存复制操作,其复杂度也是O(1)。

1.7 Mat 表达式

  如果矩阵 A 与 B 大小相同,则可以使用表达式:
  C = A + B + 1
  其执行结果是 A 的矩阵元素与 B 的矩阵元素对应相加然后再加 1 ,并将生产的矩阵赋值给 C 变量。
   下面给出Mat表达式所支持的运算。下面的列表中使用A和B表示Mat类型的对象,使用s表示Scalar对象,alpha表示double值。

加法,减法,取负:A+B,  A-B,  A+s,  A-s,  s+A,  s-A,-A缩放取值范围:A*alpha矩阵对应元素的乘法和除法:A.mul(B),  A/B,  alpha/A矩阵乘法:A*B(注意此处是矩阵乘法,而不是矩阵对应元素相乘)矩阵转置:A.t()矩阵求逆和求伪逆:A.inv()矩阵比较运算:A cmpop B, A cmpop alpha, alpha cmpop A。
此处cmpop  可以是>,>=,==,!=,<=,<。如果条件成立,则结果矩阵(8U类型矩阵)的对应元素被置为255;
否则置 0。矩阵位逻辑运算:A logicop B,  A logicop s,  s logicop A,~A,此处logicop可以是 &、| 和 ^ 。矩阵对应元素的最大值和最小值:min(A, B),  min(A, alpha),  max(A, B),max(A, alpha)。矩阵中元素的绝对值:abs(A)叉积和点积:A.cross(B),  A.dot(B)

  下面展示了 Mat 表达式的使用方法:

#include<opencv2/opencv.hpp>
#include<time.h>
#include<iostream>using namespace std;
using namespace cv;int main(int argc, char* argv[]) {system("color 2F");//eye 为构建单位矩阵Mat A = Mat::eye(4, 4, CV_32SC1);cout << "A = " << endl << A << endl << endl;Mat B = A * 3 + 1;cout << "B = " << endl << B << endl << endl;//diag(0) 为从第 1 列开始取对角线元素,col(1) 为取 B 的第 2 行元素//diag(1) 为从第 2 列开始取 (rows - 1) x (cols - 1) 对角线元素Mat C = B.diag(0) + B.col(1);   cout << "C = " << endl << C << endl << endl;cout << "C .* diag(B) = " << C.dot(B.diag(0)) << endl;//waitKey(0);system("pause");return 0;
}

运行结果:

5x4 + 8x4 + 5x4 + 5x4 = 92。

1.8 Mat 与 IplImage 和 CvMat 的转换

1.8.1 Mat 转换为 IplImage 和 CvMat

  假如你有一个以前写的函数,函数的定义为:

void mycvOldFunc(IplImage *p, …);

  函数的参数需要Ipllmage类型的指针。Mat转为Ipllmage,可以用简单的等号赋值操作来进行类型转换,这样实现:

Mat img(Size(320, 240), CV 8UC3);
IplImage iplimg = img; //转为IplImage结构
mycvOldFunc(&iplimq, …);//对Iplimq取地址

  如果要转为 CvMat 类型,操作类似:

CvMat cvimg = img;  //转为 CvMat 结构

示例:

 char path[100] = "E:\\OpenCV\\1.jpg";Mat ig = imread(path);IplImage img1 = ig;IplImage* img2 = &img1;cvShowImage("img1", img2);

  需要特别注意的是,类型转换后,IplImage 和 CvMat 与 Mat 共用同一矩阵数据,Ipllmage 和 CvMat 没有引用计数功能,如果上例中的 img 中数据被释放,iplimg 和 cvimg 也就失去了数据。因此要牢记不可将 Mat 对象提前释放。

1.8.2 IplImage 和 CvMat 格式转为 Mat

  Mat 类有两个构造函数,可以实现 Ipllmage 和 CvMat 到 Mat 的转换。这两个函数都有一个参数 copyData。如果 copyData 的值是 false,那么 Mat 将与 Ipllmage 或 CvMat 共用同一矩阵数据;如果值是 true, Mat 会新申请内存,后将 Ipllmage 或 CvMat 的数据复制到 Mat 的数据区。
  如果共用数据,Mat 也将不会使用引用计数来管理内存,需要开发者自己来管理。建议做此转换是将参数置为 true,这样内存管理变得简单。

Mat::Mat(const CvMat* m, bool copyData = false)
Mat::Mat(const IplImage* img, bool copyData = false)

例如:

IplImage* iplimg = cvLoadImage("1.jpg",1);
Mat im(iplimg, true);

2 常用的数据结构和函数

2.1 点的表示:Point 类

  Point 类数据结构表示了二维坐标系下的点,即由其图像坐标 x 和 y 指定的 2D 点。用法如下:

 Point point;point.x = 10;point.y = 8;//或者Point point = Point(10, 8);//另外,在 OpneCV 下有如下定义:typedef Point_<int> Point2i;typedef Point2i Point;typedef Point_<float> Point2f;

  所以,Point_< int > 、Point2i、Point 互相等价,Point_< float > 、Point2f 互相等价。

2.2 颜色的表示:Scalar 类

  Scalar() 表示有四个元素的数组,在 OpenCV 中被大量用于传递像素值,如果用不到第四个参数,则不必写出来。
  如果给出以下颜色参数表达式:

 Scalar(a, b, c);

  那么定义的 RGB 颜色值:红色分量为 c ,绿色分量为 b,蓝色分量为 a 。
  Scalar 类的源头为 Scalar_ 类,而 Scalar_ 类是 Vec4x 的一个变种,我们常用的 Scalar 其实就是 Scalar< double >。这就解释了为什么很多函数的参数输入可以是 Mat ,也可以是 Scalar。

2.3 尺寸的表示:Size 类

  Size 类的相关源码:

 typedef Size_<int> Size2i;typedef Size2i Size;

  其中,Size_ 是个模板类,Size_< int > 、Size2i、Size 这三个类型名等价。
  对于 Size_ 模板类的定义中,我们使用最频繁的是下面这个构造函数:

 Size_(_Tp _width, _Tp _heigth);//模板类的高度和宽度_Tp width, height;//于是可用 XXX.width 与 XXX.heigth 分别表示其宽度和高度。

2.4 矩形的表示:Rect 类

  Rect 类的成员变量有 x、y、width、heigth,分别为左上角点的坐标和矩形的宽和高。常用的成员函数有:Size() 返回值为 Size,area() 返回矩形的面积,contains(Point) 判断点是否在矩形内,inside(Rect) 判断矩形是否在矩形内,tl() 返回左上角点坐标,br() 返回右下角点坐标。若是想求两个矩形的交集和并集,可用如下格式:

 Rect rect = rect1 & rect2;Rect rect = rect1 | rect2;

  若想让矩形进行平移操作和缩放操作,可以这样写:

 Rect rectShift = rect + point;Rect rectScale = rect + size;

2.5 颜色空间转换:cvtColo()函数

  cvtColor() 函数是 OpenCV 中的颜色空间装换函数,可以实现 RGB 颜色空间想 HSV、HIS 等颜色空间转换,也可以转换为灰度图像。原型如下:

 void cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0)

  第一个参数为输入图像,第二个参数我输出图像,第三个参数为颜色空间转换的标识符(见下表),第四个参数为目标图像的通道数,若该参数是 0,则表示目标图像取源图像的通道数。
  下面是一个调用示例:

 cvtColor(srcImage, dstImage, COLOR_GRAY2BGR);   //原始图转化为灰度图

  需要注意的是:OpenCV 中默认的图片通道存储顺序是 BGR ,即蓝绿红,而不是 RGB。
  下面给出颜色空间转换的简单代码:

#include<opencv2/opencv.hpp>using namespace std;
using namespace cv;int main(int argc, char** argv)
{//1.载入图片Mat srcImage = imread("8.jpg"),dstImage;//2.转换颜色空间cvtColor(srcImage, dstImage, COLOR_BGR2Lab);//3.显示原图和效果图imshow("原图", srcImage);imshow("效果图", dstImage);waitKey();//system("pause");return 0;
}

运行结果:

2.6 其他常用知识

  ● Matx 是个轻量级的 Mat ,必须在使用前规定好大小,比如一个 2 * 3 的 float 型的 Matx,可以声明为 Matx23f。
  ● Vec 是 Matx 的一个派生类,是一个一维的 Matx ,跟 vector 很相似。
  ● Range 类其实就是为了使 OpenCV 的使用更像 MATLAB 而产生的。
  ● OpenCV 中防止内存泄漏的函数有 alignPtr、alignSize、allocate、deallocate、fastMalloc、fastFree 等。
  ● <math.h> 里的一些函数使用起来很方便,有计算向量角度的函数 fastAtan2、计算立方根的函数 cubeRoot、向上取整函数 cvCeil、向下取整的函数 cvFloor、四舍五入的函数 cvRound 等。还有一些类似于 MATLAB 里的函数,比如 cvIsInf 判断自变量是否无穷大,cvIsNaN 判断自变量是否不是一个数。
  ● 显示文字相关的函数有 getTextSize、cvInitFont、putText。
  ● 作图相关的函数有 circle、clipLine、ellipse、ellipse2Poly、line、rectangle、polylines、类 LineIterator。
  ● 填充相关的函数有 fillConvexPoly、fillPoly。
  ● OpenCV 中 RNG() 函数的作用为初始化随机数状态的生成器。

3.基本图形的绘制

  便于代码的编写,先在开头加上宏定义:

 #define WINDOW_WIDTH 600    //定义窗口的大小

3.1 DrawEclipse() 函数的写法

  描述:自定义的绘制函数,实现了绘制不同角度、相同尺寸的椭圆

 void DrawEclipse(Mat img, double angle){int thickness = 2;int lineType = 8;ellipse(img,Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), //中心点Size(WINDOW_WIDTH / 4, WINDOW_WIDTH / 16), //大小位于该尺寸的矩形内angle,     //旋转角度0,        //拓展的弧度从 0 到 360360,Scalar(255,129,0),      //图形颜色 ,该配置代表蓝色thickness,        //线宽为 2lineType);       //线型为 8 (8 联通线型)}

  此函数的解析如下:
  函数中调用了 OpenCV 的 ellipse 函数,将椭圆画到图像 img 上,椭圆中心点为 (WINDOW_WIDTH / 2, WINDOW_WIDTH / 2),并且大小位于矩形 (WINDOW_WIDTH / 4, WINDOW_WIDTH / 16) 内。椭圆旋转角度为 angle,拓展的弧度从 0 到 360 度。图形颜色为 Scalar(255,129,0) 代表的蓝色,线宽 thickness 为 2,线型 lineType 为 8(8 联通线型)。

3.2 DrawFilledCircle() 函数的写法

  描述:自定义的绘画函数,实现了实心圆的绘制

 void DrawFilledCircle(Mat img, Point center){int thickness = -1;int lineType = 8;circle(img,  //目标图像center,       //圆心点WINDOW_WIDTH / 32, //半径Scalar(0,0,255),    //颜色 按 GBR 为红色thickness,        //线粗lineType);  }

   函数调用了 OpenCV 中的 cirlce 函数,将圆画到图像 img 上,圆心由点 center 定义,圆的半径为 WINDOW_WIDTH / 32 , 圆的颜色为 Scalar(0,0,255),按 BGR 格式为红色,线粗定义为 thickness = -1 ,因此绘制的圆是实心的。

3.3 DrawPolygon() 函数的写法

  描述:实现了凹多变形的绘制

 void DrawPolygon(Mat img){int lineType = 8;//创建一些点Point rookPoints[1][20];rookPoints[0][0] = Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);rookPoints[0][1] = Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8);rookPoints[0][2] = Point(3 * WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);rookPoints[0][3] = Point(11 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);rookPoints[0][4] = Point(19 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);rookPoints[0][5] = Point(3 * WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);rookPoints[0][6] = Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][7] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);rookPoints[0][8] = Point(26 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);rookPoints[0][9] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);rookPoints[0][10] = Point(22 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);rookPoints[0][11] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);rookPoints[0][12] = Point(18 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);rookPoints[0][13] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 4);rookPoints[0][14] = Point(14 * WINDOW_WIDTH / 40, WINDOW_WIDTH / 8);rookPoints[0][15] = Point(WINDOW_WIDTH / 4, WINDOW_WIDTH / 8);rookPoints[0][16] = Point(WINDOW_WIDTH / 4, 3 * WINDOW_WIDTH / 8);rookPoints[0][17] = Point(13 * WINDOW_WIDTH / 32, 3 * WINDOW_WIDTH / 8);rookPoints[0][18] = Point(5 * WINDOW_WIDTH / 16, 13 * WINDOW_WIDTH / 16);rookPoints[0][19] = Point(WINDOW_WIDTH / 4, 13 * WINDOW_WIDTH / 16);const Point* ppt[1] = { rookPoints[0] };int npt[] = { 20 };fillPoly(img,  //目标图像ppt,  //多边形顶点集npt,    //多边形顶点数目1,     //要绘制的多边形数量Scalar(255, 255, 255),       //多边形颜色--白色lineType);}

  该函数调用了 OpenCV 中的 fillPoly 函数,用于将多边形画到图 img 上,其中多边形的顶点集为 ppt ,要绘制的多边形的顶点数目为 npt,要绘制的多边形数量为 1,多边形的颜色设置为白色 Scalar(255, 255, 255)。

3.4 DrawLine() 函数的写法

  描述:实现了线的绘制

 void DrawLine(Mat img, Point start, Point end)      //绘制直线{int thickness = 2;int lineType = 8;line(img,   //目标图像start,        //直线起点  end,        //直线终点Scalar(0, 0, 0),  //黑色thickness,      //线的粗细lineType);}

  该函数调用了 OpenCV 中的 line 函数,用于在图像 img 上画一条从点 start 到 end 的直线段,线的颜色为 Scalar(0, 0, 0) 代表的黑色,先的粗细为 thickness 为 2,且此线为 8 联通(lineType = 8)。

3.5 main 函数的写法

  main 函数的写法非常简单,先创建空白的 Mat 图像,然后调用绘制化学中的原子示例图,接着绘制组合图,最后显示绘制出的图像。

 int main(int argc, char** argv){//创建空白的 Mat 图像Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);Mat rookImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);//-------------1.绘制化学中的原子示例图------------------------//1.1先绘制出椭圆DrawEclipse(atomImage, 90);DrawEclipse(atomImage, 0);DrawEclipse(atomImage, 45);DrawEclipse(atomImage, -45);//1.2再绘制圆心DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2));//-------------2.绘制组合图----------------------------//2.1先绘制出椭圆DrawPolygon(rookImage);//2.2绘制矩形rectangle(rookImage,Point(0, 7 * WINDOW_WIDTH / 8),        //矩形的一个顶点Point(WINDOW_WIDTH, WINDOW_WIDTH),     //对角线上的另一个顶点Scalar(0, 255, 255),-1,8);//2.3绘制一些线段DrawLine(rookImage, Point(0, 15 * WINDOW_WIDTH / 16), Point(WINDOW_WIDTH, 15 * WINDOW_WIDTH / 16));DrawLine(rookImage, Point(WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH / 4, WINDOW_WIDTH));DrawLine(rookImage, Point(WINDOW_WIDTH / 2, 7 * WINDOW_WIDTH / 8), Point(WINDOW_WIDTH / 2, WINDOW_WIDTH));DrawLine(rookImage, Point(3 * WINDOW_WIDTH / 4, 7 * WINDOW_WIDTH / 8), Point(3 * WINDOW_WIDTH / 4, WINDOW_WIDTH));//-------------------显示绘制出的图像---------------------------imshow(WINDOW_NAME1, atomImage);moveWindow(WINDOW_NAME1, 0, 200);imshow(WINDOW_NAME2, rookImage);moveWindow(WINDOW_NAME2, WINDOW_WIDTH, 200);waitKey(0);//system("pause");return 0;}

运行结果:

OpenCV数据结构与基本绘图(Mat 类、Point类、Scalar类等)相关推荐

  1. 《OpenCV3编程入门》学习笔记4 OpenCV数据结构与基本绘图

    第4章 OpenCV数据结构与基本绘图 4.1 基础图像容器Mat 4.1.1 数字图像存储概述   图像在数码设备中的表现形式:像素点矩阵 4.1.2 Mat结构的使用 1.OpenCV1.x时代: ...

  2. 【OpenCv】c++ 入门认识 Mat 类,单通道 Mat 的基本操作

    文章目录 前言 Mat 类 Mat 类的构造方式 Mat 基本操作 单通道 Mat 的基本操作 使用成员变量 rows 和 cols 获取矩阵的行数和列数 使用成员函数 size() 来获取矩阵的尺寸 ...

  3. OpenCV 笔记(09)— 常用的数据结构和函数(Vec、Point、Scalar、Size、Rect、cvtColor)

    1. Vec 对象类型 Vec 是一个主要用于数值向量的模板类.我们可以定义向量的类型和组件的数量: Vec<double, 19> myVector 我们还可以使用任何的预定义类型: t ...

  4. OPENCV数据结构体系和常用函数

    opencv设计了一些基础的数据类型和一些帮助的数据类型 基础数据类型 : 图像类 IplImage: 矩阵类 CvMat; 可变集合类:CvSeq CvSet CvGraph; 多维柱状图混合类:C ...

  5. OpenCV(四)————认识Mat对象(C++)

    内容: 1.什么是Mat 2.Mat的属性与操作 3.创建Mat 1.什么是Mat 图像文件的内存数据对象 对于人类来说,看到一个图像时,脑子里会想到这个图像内容,比如一张帅哥的照片,在我们看来就是帅 ...

  6. 绘图用的函数及矩形类CRect和矩形结构RECT

    绘图一般在视图类的(屏幕/打印机)绘图消息响应函数OnDraw中进行,例如: void CTestView::OnDraw(CDC* /pDC/) { CTestDoc* pDoc = GetDocu ...

  7. OpenCV 中的 Scalar 类、Vec类

    转 自 http://www.bubuko.com/infodetail-1533054.html 文章目录 Scalar 类 Vec 类 Scalar 类 typedef Scalar_<do ...

  8. OpenCV简单的几何绘图的实例(附完整代码)

    OpenCV简单的几何绘图的实例 OpenCV简单的几何绘图的实例 OpenCV简单的几何绘图的实例 #include <opencv2/core.hpp> #include <op ...

  9. python @修饰符_数据结构与算法之8——抽象数据类型与python类

    就算你是特别聪明,也要学习,从头学起!--(俄国)屠格涅夫 本篇文章要说的主要是数据结构与算法和python中关于类(Class)以及异常(Error)的一些基础,虽然很简单,但是必须非常重视.只有在 ...

最新文章

  1. 弹球游戏python代码含记分模式_python编写弹球游戏的实现代码
  2. VS2010 定位文件在solution中的位置
  3. Windows Azure 数据安全(清理和泄漏)
  4. SqueezeNet
  5. vue开发 - 将方法绑定到window对象,给app端调用
  6. 2699元起!格力首款5G手机悄然上架:骁龙765G处理器
  7. pb程序怎么发布到iis_怎么使用抖音小程序第三方平台系统开发制作发布抖音小程序+教程...
  8. 每一次结束只是一次新的起点,深有体会。
  9. 打开游戏要运行19.8亿次 if 语句?黑客嘲讽RockStar游戏代码太烂了
  10. 萤石云平台接入_前端接入萤石云视频
  11. visio2016上下标
  12. GAN网络-简单明了
  13. Katalon Recorder简介与使用
  14. 【COCI 2011】送票
  15. QCharts QValueAxis使用
  16. 分享2个优质牛肉干的挑选方法
  17. 必应每日壁纸API HTML 使用必应每日API为背景 css 背景图片 加模糊 遮罩
  18. OpenCV图像处理 空间域图像增强(图像锐化 1 基于拉普拉斯算子)
  19. GoPower运动功率计
  20. Mac OS terminal 查看内存使用情况的命令

热门文章

  1. 金山网盾监测:游戏玩家下载西西游戏外挂会中大量***
  2. 设置Socket缓冲区
  3. 用Leangoo敏捷看板工具管理 产品线路图
  4. 一次性搞懂Spring Boot 注解原理与自动装配原理,图文并茂,万字长文!
  5. 图解计算机中数据的表示形式
  6. 面试官:CAP都搞不清楚,别跟我说你懂微服务!
  7. 免费!!3天,吃透JVM!(限时领)
  8. 面试被问到秒杀系统,这个点你一定得答到!
  9. 12位黄金技术大佬发出警告:一大波必读好书向你袭来!
  10. VM 与容器之争!Docker赢了!