您的位置:首页 > 运维架构

OpenCV从入门到放弃(三):Core组件细讲

2016-09-07 16:33 645 查看
Core组件由名字就知道是最核心功能的模块:在Core组件中,包含了最基本的数据结构,动态数据结构,画图的一些函数和一些系统函数.下面依次来讲一下这些基本的功能.Core组件是很重要的相当于修楼房的砖块,要把一些基本的概念弄懂.

一:基本数据结构

1.Mat类(最基本的数据结构)

1.概念

1.Mat不仅仅是一个图像容器类,同时也是一个通用的矩阵类.
2.不必再手动为其开辟空间,也不必在不需要的时候立即将他的空间释放
3.Mat是一个类,由两个数据部分组成:
1.矩阵头:矩阵尺寸,存储方法,存储地址等等所有相关信息(矩阵头的尺寸是常数值)
2.指向存储所有像素值数据块的指针.
4.赋值运算符和复制构造函数只会复制信息头和指向数据块指针的值.但是不会完整的复制一个矩阵(为了性能和避免内存溢出考虑).所以有多个对象引用同一个值矩阵,改变其中一个对象有改变其他的对象的可能.
5.使用clone()或者copyTo()来深层复制一幅图像的矩阵.
6.前面已经知道一个矩阵可以被多个Mat对象引用,那么最后一个使用这个矩阵的对象,负责清理矩阵。


2.常用函数

1.构造函数(主要介绍下面这两种)

Mat (int rows, int cols, int type, const Scalar &s)
Rows:行数
Cols:列数
Type:类型 CV_[位数][带符号与否][类型前缀][通道数]
例:CV_8UC3表示使用8位的unsighed char类型.每个像素由三个元素组成的三通道.
类型汇总:
CV_8U  (8 bit 无符号整形0~255)
CV_8UC1 (1通道)  CV_8UC2 (2通道)  CV_8UC3 (3通道)  CV_8UC4(4通道)

CV_8S   (8 bit有符号整形-128~127)
CV_8SC1 (1通道)  CV_8SC2 (2通道)   CV_8SC3 (3通道)  CV_8SC4 (4通道)

CV_16U  (16 bit 无符号整形0~65535)
CV_16UC1 (1通道)  CV_16UC2 (2通道)   CV_16UC3 (3通道)   CV_16UC4 (4通道)

CV_16S  (16 bit 有符号整形-32768~32767)
CV_16SC1(1通道)   CV_16SC2(2通道)   CV_16SC3(3通道)   CV_16SC4(4通道)

CV_32S  (32 bit 有符号整形-2147483648~2147483647)
CV_32SC1   CV_32SC2    CV_32SC3  CV_32SC4

CV_32F  (32 bit 浮点)
CV_32FC1   CV_32FC2  CV_32FC3   CV_32FC4

CV_64F   (64 bit 浮点)
CV_64FC1   CV_64FC2  CV_64FC3  CV_64FC4

Scalar:颜色类..具体看下面的Scalar类.

Mat (int ndims, const int *sizes, int type, const Scalar &s)
Ndims:维数.
*size:一个数组,表示相应维数下面的具体数量
Type:和上面一样
Scalar:和上面一样.


2.empty()函数(判断是否Mat是否有元素,或者是否分配了图像数据)

使用方法:Mat对象.empty()
返回一个bool对象.


3.channels()函数

返回一个Mat对象的通道数.


4.create()函数

这个方法不能够为矩阵设置初值,只是在改变尺寸的时候重新为矩阵开辟内存而已.


5.type()函数 返回的是一个int值.返回mat的类型.

3.例子

1.Mat的初始化和输出

我们在这里使用的初始化是标准的Mat()构造函数的方法,输出方法是Python风格的输出(以后也会固定这样的创建和输出风格.)





按照pyton的方式输出矩阵,同时还有一点点红色出现在框里面.这是矩阵的输出方式.

2.Mat的内存管理方式(这个例子非常重要)

代码:





结果及其分析:

1.首先就一整个来说,



因为namewindow()了六个窗口.但是其中有一个”image”窗口变色了.



是因为上面这段代码初始化了一个灰度图(CV_8U)然后在”image”命名的这个窗口显示导致的.

2.按一下回车.

其他都没有变,那个image窗口变小了,而且颜色也变了.



是因为下面这段代码导致的



也就是说.这个时候的image1这个mat对象被重新改变了size和值.

3.按一下回车



其他的没有变,只有“image”这个窗口变了。是下面这段代码改变的。



这段代码新建了一个image2的mat对象,并且是三通道彩色的(CV_8UC3)。初始的值设为红色。然后Image这个窗口用来显示image2这个对象了。(这个例子说明。一个窗口用了之后还能够给其他的对象再用。)

4.按一下回车



这次改变就蛮大了.



上面这段代码先是建立了一个image3的对象,并且都载入了一张图像

原图是这个样子的



然后就浅复制给image4,然后就深复制给image5.然后image3翻转。

我们看到,image4和image3都翻转了。但是image5没有翻转。因为image5是深度复制变得独立。不受image3翻转的影响。

5.按一下回车



Image窗口变成灰色,



得到的结论是:

1.可以随时用create方法分配或者重新分配图像的数据块,要是图像已经分配,首先其原来的内容会被释放。(要是新的大小和类型都与原来的相同,就不会重新分配内存)

2.一旦没有了指向cv::Mat对象的引用,那么这个对象就会被自动释放。

3.在两个图像之间赋值的时候(包括赋值=或者复制构造函数等等),图像数据并不会被复制,此时两个图像都指向同一个内存块。所以,这样的出来的图像有可能会影响到其他的图像

4.要想深度复制图形的话,可以用copyTo()方法或者clone()方法。

5.如果你需要把一个图像复制到另外一个图像中,但是两者的数据类型是不一样的,那么就要是用convertTo方法

2.Scalar类(颜色表示)

1.概念

1.Scalar类源头为scalar_类,typedef  Scalar_< double >     cv::Scalar后成为scalar类
2.Scalar表示具有4个元素的数组,一般在OpenCV中被用来传递像素值.


2.函数

就举一个简单的构造函数

cv::Scalar_< _Tp >::Scalar_     ( _Tp  v0,_Tp  v1,_Tp  v2 = 0,_Tp  v3 = 0 )


3.用法

一般的用法就是Scalar(a,b,c)表示一个颜色对象.注意:顺序分别是蓝,绿,红.在上面Mat的构造函数中就有Scalar的使用.回过头来看一下是不是豁然开朗?

3.Point类(点的表示)

1.概念

Point类表示二维坐标系下面的点.


2.函数

举两个常用的构造函数

Point_ (_Tp _x, _Tp _y)   //代入坐标
Point_ (const Point_ &pt)  //代入点


3.用法

Point p=Point(1,2)   //p就表示一个坐标(1,2)的点
等价于
Point p;
p.x=1;
p.y=2;


4.Size类(尺寸的表示)

1.概念

就是表示尺寸的一个类,来源于Size_()


2.函数

Size_ (_Tp _width, _Tp _height)
其实就是宽和高


3.用法

Size(3,4)   //宽和高分别是3,4


5.Rect类(矩形的表示)

1.概念

表示一个矩形的类,来源是Rect_< _Tp >


2.函数

常用的构造函数:
Rect_ (_Tp _x, _Tp _y, _Tp _width, _Tp _height) //传坐标和宽高
Rect_ (const Rect_ &r)       //传rect对象
Rect_ (const Point_< _Tp > &org, const Size_< _Tp > &sz)  //传入点(得到坐标)尺寸(得到宽高)

普通函数
_Tp  area () const    //返回矩形面积

Point_< _Tp >  br () const   //返回右下角点坐标

bool  contains (const Point_< _Tp > &pt) const   //判断某点是否在矩形内

Size_< _Tp >    size () const   //返回当前矩形的Size

Point_< _Tp >  tl () const  //返回左上角点坐标


3.用法

就这么用…

二.绘图函数

首先要讲一下,接下来的大部分函数都在cv::LineIterator这个类下面.画直线等等函数在imgproc这个模块中.之所以放在Core这个组件讲,是因为前面刚刚讲了Opencv中的一些基本的数据结构.绘图函数本身也是十分重要的函数且用到之前讲过的概念.因此,提前放在这里讲.下面是绘图函数的官方文档.

http://docs.opencv.org/master/d6/d6e/group__imgproc__draw.html#ga7078a9fae8c7e7d13d24dac2520ae4a2

1.直线(line)

1.函数及其使用方式

void cv::line   ( InputOutputArray  img,
Point   pt1,
Point   pt2,
const Scalar &      color,
int     thickness = 1,
int     lineType = LINE_8,
int     shift = 0
)
Img:待操作的图片
pt1:起点
Pt2:终点
Color:颜色
Thickness:厚度(粗细)
LineType:直线类型
Shift:


2.实例

代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
//画直线等等函数在imgproc中
#include <opencv2/imgproc.hpp>

int main()
{
//创建一个窗口并且以Tset为标示
cv::namedWindow("Test");
//创建空白的图像
cv::Mat Image = cv::Mat::zeros(600, 600, CV_8UC3);
//起点和终点
cv::Point p1(100, 200);
cv::Point p2=cv::Point(100, 400);

cv::Point p3(150, 200);
cv::Point p4 = cv::Point(150, 400);

cv::Point p5(200, 200);
cv::Point p6 = cv::Point(200, 400);

cv::Point p7(250, 200);
cv::Point p8 = cv::Point(250, 400);
//画直线1
cv::line(Image, p1, p2, cv::Scalar(0, 0, 255), 1, 8, 0);

//画直线2(改变了线条粗细)
cv::line(Image, p3, p4, cv::Scalar(0, 0, 255), 10, 8, 0);

//画直线3(改变了线条类型)
cv::line(Image, p5, p6, cv::Scalar(0, 0, 255), 1, 4, 0);

//画直线4(改变了shift)
cv::line(Image, p7, p8, cv::Scalar(0, 0, 255), 1, 8, 0);

cv::imshow("Test", Image);
cv::waitKey(0);
return 0;
}


效果:



2.椭圆(ellipse)

1.函数使用方式

void cv::ellipse    ( InputOutputArray      img,
Point   center,
Size    axes,
double      angle,
double      startAngle,
double      endAngle,
const Scalar &      color,
int     thickness = 1,
int     lineType = LINE_8,
int     shift = 0
)

Img:待操作的图片
Center:椭圆中心点坐标
Axes:是一个size的类型,其实就是长短轴的大小(最终肯定是位于一个矩形框里面)
Angle:表示椭圆的旋转角度
startAngle:开始扩展弧度
endAngle:结束的扩展弧度
Color:颜色
Thickness:厚度(粗细)
LineType:线类型
Shift:


2.实例

代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
//画直线等等函数在imgproc中
#include <opencv2/imgproc.hpp>

int main()
{
//创建一个窗口并且以Tset为标示
cv::namedWindow("Test");
//创建空白的图像
cv::Mat Image = cv::Mat::zeros(600, 600, CV_8UC3);

//中心点和长短轴
cv::Point c1(100, 200);
cv::Size ax1(50, 100);

cv::Point c2(250, 200);
cv::Size ax2(50, 100);

cv::Point c3(400, 200);
cv::Size ax3(50, 100);

//画椭圆1,中心(100,200),短轴50,长轴100,旋转角度为0°,扩展弧长为(0,360)
//颜色,粗细等等可以类比前面讲过的直线
cv::ellipse(Image, c1, ax1, 0, 0, 360, cv::Scalar(0, 0, 255), 1, 8, 0);

//画椭圆2,中心(250,200),短轴50,长轴100,旋转角度为30°,扩展弧长为(0,360)
//颜色,粗细等等可以类比前面讲过的直线
cv::ellipse(Image, c2, ax2, 30, 0, 360, cv::Scalar(0, 0, 255), 1, 8, 0);

//画椭圆3,中心(400,200),短轴50,长轴100,旋转角度为30°,扩展弧长为(90,360)
//颜色,粗细等等可以类比前面讲过的直线
cv::ellipse(Image, c3, ax3, 30, 90, 360, cv::Scalar(0, 0, 255), 1, 8, 0);

cv::imshow("Test", Image);
cv::waitKey(0);
return 0;
}


效果:

看了效果之后,应该对于这个椭圆的各个角度应该有了认识.



3.矩形(rectangle)

1.函数使用方式

方式一:
void cv::rectangle  ( InputOutputArray  img,
Point  pt1,
Point  pt2,
const Scalar &  color,
int  thickness = 1,
int  lineType = LINE_8,
int  shift = 0
)
Img:待操作的图片
pt1:顶点坐标
Pt2:对角线那个顶点的坐标
Color:颜色
Thickness:厚度(粗细)
LineType:线类型
Shift:

方式二:
void cv::rectangle  ( Mat &  img,
Rect  rec,
const Scalar &  color,
int  thickness = 1,
int  lineType = LINE_8,
int  shift = 0
)
Img:待操作的图片
Rec:矩阵对象
Color:颜色
Thickness:厚度(粗细)
LineType:线类型
Shift:


2.实例

代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
//画直线等等函数在imgproc中
#include <opencv2/imgproc.hpp>

int main()
{
//创建一个窗口并且以Tset为标示
cv::namedWindow("Test");
//创建空白的图像
cv::Mat Image = cv::Mat::zeros(600, 600, CV_8UC3);

//两个顶点的方式创建矩形框
cv::Point p1(100, 200);
cv::Point p2(300, 400);
cv::rectangle(Image, p1, p2, cv::Scalar(0, 0, 225), 1, 8, 0);

//rect的方式创建矩形框
cv::rectangle(Image, cv::Rect(300, 300, 100, 200), cv::Scalar(255, 0, 0), 1, 8, 0);

cv::imshow("Test", Image);
cv::waitKey(0);
return 0;
}


结果:



4.圆(circle)

1.函数使用方式

void cv::circle     ( InputOutputArray      img,
Point   center,
Int     radius,
const Scalar &      color,
int     thickness = 1,
int     lineType = LINE_8,
int     shift = 0
)
Img:待操作的图片
center:中心点坐标
Radius:半径
Color:颜色
Thickness:厚度(粗细)
LineType:线类型
Shift:


2.实例

代码:

#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
//画直线等等函数在imgproc中
#include <opencv2/imgproc.hpp>

int main()
{
//创建一个窗口并且以Tset为标示
cv::namedWindow("Test");
//创建空白的图像
cv::Mat Image = cv::Mat::zeros(600, 600, CV_8UC3);

//创建圆
cv::Point c1(100, 200);
cv::circle(Image, c1, 50, cv::Scalar(0, 0, 255), 1, 8, 0);

cv::imshow("Test", Image);
cv::waitKey(0);
return 0;
}


结果:

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  图像 opencv 数据结构