关闭

core组件之基本数据结构和绘图函数

120人阅读 评论(0) 收藏 举报
分类:

在本节中,总结了以下内容:

  • Mat类的基本用法
  • 常用的数据结构(如Point,Size等)
  • 基本的绘图操作(rectangle(),circle(),ellipse())

【Mat类的基本介绍】

Mat类是一个图像容器类,同时也是一个通用的矩阵类,可以用它来创建和操作多维矩阵。

创建一个Mat对象的方法有多种,以下仅介绍我比较常用的一些。

方法一、使用Mat()构造函数(最常用)

如:Mat M(3, 2, CV_8UC3,Scalar(0,0,255));

对于二维多通道图像,分别定义其尺寸,即行数(rows)和列数(cols);然后指定存储元素的数据类型和通道数(如CV_8UC3)以及初始化的值(如Scalar(0,0,255))。
行数和列数自然很好理解,那么这里的CV_8UC3是什么意思呢?
OpenCV规定了存储元素的数据类型和每个矩阵点的通道数,规则如下:
CV_[the number of bits of per item][signed or unsigned][type prefix]C[the channel number]
即,CV_[位数][带符号与否][类型前缀]C[通道数](前缀类型是什么我还不理解。。。)
因此,CV_8UC3则表示使用8位的unsigned char型,每个像素由三个元素组成三通道。

而初始值Scalar(0,0,255)又表示什么意思呢?
首先要知道Scalar是一个类,表示具有4个元素的数组,它在OpenCV中常用于表示像素值(如RGB颜色值,通常只写三个参数,最后一个不用写),如Scalar(0,0,255)表示蓝色分量为0,绿色分量为0,红色分量为255。(注意:我这里是写错了吗?用Scalar(0,0,255)表示一个RGB颜色值怎么是”蓝色分量为0,绿色分量为0,红色分量为255“呢?——其实没有写错,因为OpenCV默认的图片通道存储顺序是BGR!)
其次,在Mat的构造函数中,就是用Scalar(0,0,255)来初始化每一个像素点。

如果直接cout << "M=" << endl << M << endl;
可以看到:

M=
[  0,   0, 255,   0,   0, 255;
   0,   0, 255,   0,   0, 255;
   0,   0, 255,   0,   0, 255]
方法二、采用Matlab式的初始化方式

zeros()(全0矩阵),ones()(全1矩阵),eye()(正对角线为1的矩阵)这三个函数。需要指定尺寸和数据类型,比较简单,直接上例子了。

Mat M1 = Mat::zeros(3, 2, CV_8UC1);
Mat M2 = Mat::ones(3, 2, CV_8UC1);
Mat M3 = Mat::eye(3, 2, CV_8UC1);

M1=
[  0,   0;
   0,   0;
   0,   0]
M2=
[  1,   1;
   1,   1;
   1,   1]
M3=
[  1,   0;
   0,   1;
   0,   0]
方法三、对小矩阵使用逗号分隔式初始化函数

Mat M4 = (Mat_<float>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);

M4=
[1, 2, 3;
4, 5, 6;
7, 8, 9]
方法四、使用成员函数clone()copyTo()

在介绍clone()copyTo()函数之前,先来看下面一段代码。

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
       Mat img(300, 300, CV_8UC3, Scalar(155, 155, 0));
       Mat copyImg1(img);//拷贝构造函数,浅拷贝

       putText(copyImg1, "test", Point(10, 30), FONT_HERSHEY_SIMPLEX, 1, Scalar::all(0));
       imshow("srcImg", img);
       imshow("copyImg1", copyImg1);
       waitKey(0);
       return 0;
}

以上这段代码,我们通过Mat的拷贝构造函数把原图img复制给copyImg1,然后再对copyImg1做一些操作(此处,用putText()函数在copyImg1上写一行字),最后显示出来,结果如下:
这里写图片描述

可以看到,明明只是对copyImg1进行了操作,但是原图显示的结果也输出了一行文字,可见copyImg1和img其实共享同一个矩阵,这是因为OpenCV中使用了引用计数机制。

那么,如果把拷贝构造函数替换成clone()copyTo()函数,即

把 Mat copyImg1(img);//拷贝构造函数,浅拷贝
替换成为
Mat copyImg1 = img.clone();
或
Mat copyImg1;
img.copyTo(copyImg1);

测试结果如下:
这里写图片描述

可见,对copyImg1的操作不影响原img,也就是说,clone()和copyTo()函数是对原图像的深拷贝。

【常用的数据结构和函数】

1、点的表示:Point类

Point类表示二维坐标系下的点,用法如下:

Point pt(3, 4);

Point pt;
pt.x = 3;
pt.y = 4;

初学者需要理解的是,在OpenCV中,有如下定义:

typedef Point_<int> Point2i;
typedef Point2i Point;
typedef Point_<float> Point2f;
...

所以,Point_<int>Point2iPoint是等价的…

2、颜色的表示:Scalar类

上面有讲,不再赘述。

3、尺寸的表示:Size类

常用的方法如下:

Size sz(100,50);//width为100,height为50

cout << "sz = " << sz <<endl;
打印的结果为:
sz = [100 x 50]

需要了解的是,Size类的定义是这样子的:

typedef Size_<int> Size2i;
typedef Size2i Size;
...

其中,Size_是一个模板类,这个Size_类里面又重载了一些构造函数,定义了一些方法(如计算尺寸面积的函数area())。

4、矩形的表示:Rect类

Rect类的成员变量有x,y,width,height,分别表示左上角点的坐标和矩形的宽和高,如图:
这里写图片描述
Rect类的构造方法有

Rect() 
Rect(double[] vals) 
Rect(int x, int y, int width, int height) //常用 
Rect(Point p1, Point p2) //常用
Rect(Point p, Size s) 

Rect类常用的方法有:

double area() //面积
Point br() //bottom-right右下角
Rect clone() 
boolean contains(Point p) //判断点p是否在矩形内
boolean inside(Rect rect) //判断矩形rect是否在矩形内 
Size size() //格式为[width*height]
Point tl() //top-left左上角

此外,神奇的是:如果想求两个矩形的交集和并集,可以用如下形式:

Rect rect3 = rect1 & rect2;
Rect rect4 = rect1 | rect2;

如果想让矩形进行平移或缩放操作,可以这样写:

rect1 = rect1 + Point(20,20);
rect1 = rect1 + Size(35,70);

示例:

#include <opencv2/core/core.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
int main()
{
       cv::Mat image = cv::imread("E:/image/dog.jpg");
       cv::imshow("result1", image);
       cout << "image.size() = " << image.size() << endl;
       cv::Rect rect1(100, 50, 300, 150);
       //cv::Rect rect1(cv::Point(100, 50), cv::Point(400, 200));
       cout << "rect1 = " << rect1 << endl;
       cout << "rect1.area() = " << rect1.area() << endl;
       cout << "rect1.br() = " << rect1.br() << endl;//右下角
       cout << "rect1.tl() = " << rect1.tl() << endl;//左上角
       cout << "rect1.size() = " << rect1.size() << endl;
       cv::Mat roi;
       //roi = image(rect1);
       image(rect1).copyTo(roi);
       cv::imshow("result2", roi);
       cv::waitKey(0);
       return 0;
}

结果:
这里写图片描述

【基本绘图函数】

1、画矩形
void cv::rectangle
(
InputOutputArray img,
Point pt1,              //左上角
Point pt2,              //右下角
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 
)
或
void cv::rectangle
(
Mat & img,
Rect rec,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 
)
2、画圆形
void cv::circle
(
InputOutputArray img,
Point center,
int radius,
const Scalar & color,
int thickness = 1,
int lineType = LINE_8,
int shift = 0 
)
3、画椭圆官方文档
void cv::ellipse
(
InputOutputArray img,          
Point center,            //椭圆的中心点
Size axes,               //椭圆对应的矩形的大小
double angle,            //椭圆主轴相对于x轴的角度
double startAngle,       //椭圆线的起点
double endAngle,         //椭圆线的终点
const Scalar & color,    //线条的颜色
int thickness = 1,       //线条宽度
int lineType = LINE_8,   //线条类型(不用管)
int shift = 0 
)

对应下图来理解个参数的含义(图片来自官方文档)
这里写图片描述

示例:

#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <iostream>
using namespace std;
using namespace cv;
const int WIN_WIDTH = 400;
int main()
{
       Mat img(WIN_WIDTH, WIN_WIDTH, CV_8UC3, Scalar(255, 255, 255));

       double angle = 30;
       int thickness = 2;
       int lineType = 8;
       ellipse(img, Point(WIN_WIDTH / 2, WIN_WIDTH / 2), Size(WIN_WIDTH / 4, WIN_WIDTH / 8), angle, 0, 360, Scalar(0, 0, 0), thickness, lineType);

       Rect rect(100, 100, 200, 200);
       rectangle(img, rect, Scalar(0, 0, 0), thickness, lineType);
       int r = WIN_WIDTH / 20;
       circle(img, Point(WIN_WIDTH / 2, WIN_WIDTH / 2), r, Scalar(0, 0, 0), thickness, lineType);
       imshow("img", img);
       waitKey(0);
       return 0;
}

结果:
这里写图片描述

0
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

数据结构:数组的操作(C语言描述)

数据的在计算机的存储方式分为:连续存储【数组】,非连续存储【链表、树、图and so on】;今天讨论的将是数组,包括数组的创建、打印输出,在数组后面追加元素,判断数组是否为空,判断数组是否为满,在数...
  • lpp0900320123
  • lpp0900320123
  • 2014-02-28 22:29
  • 8139

数据结构图和图的基本操作

图和图的基本操作,.图的表示和实现,图的应用,.贪心算法
  • qinyf2015
  • qinyf2015
  • 2016-08-11 11:38
  • 3862

数据结构---图(数组表示法)

// MGraph_array.cpp : Defines the entry point for the console application. /*-----CODE FOR FUN------...
  • Dream_WHui
  • Dream_WHui
  • 2015-03-02 17:28
  • 1716

【openCV入门之三】数据结构和绘图函数

OpenCV数据结构和绘图函数   1.        Mat数据结构详解 1.1.       Mat结构组成和适用方法 l  ...
  • jcjx0315
  • jcjx0315
  • 2016-09-04 12:24
  • 488

OpenCV学习笔记(二十一)——绘图函数core OpenCV学习笔记(二十二)——粒子滤波跟踪方法 OpenCV学习笔记(二十三)——OpenCV的GUI之凤凰涅槃Qt OpenCV学习笔记(二十

OpenCV学习笔记(二十一)——绘图函数core  在图像中,我们经常想要在图像中做一些标识记号,这就需要绘图函数。OpenCV虽然没有太优秀的GUI,但在绘图方面还是做得很完整的。这里就...
  • GarfieldEr007
  • GarfieldEr007
  • 2016-04-14 13:48
  • 875

GDI+ 画刷、矩阵、基本绘图函数、文字、图像

本文转自:http://blog.csdn.net/andywangcn/article/details/6270285   主要画刷 单色画刷SolidBrush SolidBrush(...
  • lx198986611235
  • lx198986611235
  • 2014-06-07 18:23
  • 546

opencv 基本绘图函数总结

#include "opencv2/calib3d/calib3d.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/...
  • hust_bochu_xuchao
  • hust_bochu_xuchao
  • 2017-03-06 20:35
  • 1543

opencv︱图片与视频的读入、显示、写出、放缩与基本绘图函数介绍

本文来自于段力辉 译《OpenCV-Python 中文教程》 一、图片 + 读入、显示、写出opencv中读入、显示、写出图片:cv2.imread(), cv2.imshow(), cv2.imwr...
  • sinat_26917383
  • sinat_26917383
  • 2017-04-09 15:34
  • 1647

OpenCv学习笔记(七)---OpenCv中的基本绘图函数,圆,椭圆,线段,矩形,多边形的绘制(1)

(一)本节教程的目的 本节你将学到: 1--如何使用Point在图像中定义2D点 2--如何以及为何使用Scalar 3--用OpenCv的函数Line绘直线 4--用OpenCvd的函数el...
  • maweifei
  • maweifei
  • 2016-04-26 11:43
  • 16405

opencv基本绘图函数--点,线,矩形,圆等

opencv提供的一些绘图函数,来简单的绘制一个简易的图形,包括线段、矩形、椭圆、多边形等。 1.线段 opencv提供了line()函数来对直线的绘制。其原型如下: CV_EXPORTS_W vo...
  • piaoxuezhong
  • piaoxuezhong
  • 2017-01-13 21:28
  • 3399
    个人资料
    • 访问:3108次
    • 积分:261
    • 等级:
    • 排名:千里之外
    • 原创:24篇
    • 转载:1篇
    • 译文:0篇
    • 评论:0条