Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于
所有文章 工具

Tim

一枚野生程序员~

  • 主页
  • 分类
  • 标签
  • 归档
  • 关于

Mat与基本图形绘制

阅读数:次 2018-08-30
字数统计: 2.6k字   |   阅读时长≈ 11分

Mat对象与IplImage对象

  • Mat对象OpenCV2.0之后引进的图像数据结构、自动分配内存、不存在内存泄漏的问题,是面向对象的数据结构。分了两个部分,头部与数据部分
  • IplImage是从2001年OpenCV发布之后就一直存在,是C语言风格的数据结构,需要开发者自己分配与管理内存,对大的程序使用它容易导致内存泄漏问题,下面是IplImage结构体的定义:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
typedef struct _IplImage
{
int nSize; // IplImage大小
int ID; // 版本 (=0)
int nChannels; // 大多数OPENCV函数支持1,2,3 或 4 个通道
int alphaChannel; // 被OpenCV忽略
int depth; // 像素的位深度,主要有以下支持格式: IPL_DEPTH_8U, IPL_DEPTH_8S, IPL_DEPTH_16U,IPL_DEPTH_16S, IPL_DEPTH_32S,IPL_DEPTH_32F 和IPL_DEPTH_64F
char colorModel[4]; // 被OpenCV忽略
char channelSeq[4]; // 同上
int dataOrder; // 0 - 交叉存取颜色通道, 1 - 分开的颜色通道.只有cvCreateImage可以创建交叉存取图像
int origin; // 图像原点位置: 0表示顶-左结构,1表示底-左结构
int align; // 图像行排列方式 (4 or 8),在 OpenCV 被忽略,使用 widthStep 代替
int width; // 图像宽像素数
int height; // 图像高像素数
struct _IplROI *roi; // 图像感兴趣区域,当该值非空时,只对该区域进行处理
struct _IplImage *maskROI; // 在 OpenCV中必须为NULL
void *imageId; // 同上
struct _IplTileInfo *tileInfo; //同上
int imageSize; // 图像数据大小(在交叉存取格式下ImageSize=image->height*image->widthStep),单位字节
char *imageData; // 指向排列的图像数据
int widthStep; // 排列的图像行大小,以字节为单位
int BorderMode[4]; // 边际结束模式, 在 OpenCV 被忽略
int BorderConst[4]; // 同上
char *imageDataOrigin; // 指针指向一个不同的图像数据结构(不是必须排列的),是为了纠正图像内存分配准备的

} IplImage;

Mat对象使用

基本概念

通道

把图像分解成一个或多个颜色成分!

  • 单通道:一个像素点只需一个数值表示,只能表示灰度,0为黑色
  • 三通道:RGB模式,把图像分为红绿蓝三个通道,可以表示彩色,全0表示黑色
  • 四通道:在RGB基础上加上alpha通道,表示透明度,alpha=0表示全透明
  • 双通道:双通道图像不常见,通常在程序处理中会用到,如傅里叶变换,可能会用到,一个通道为实数,一个通道为虚数,主要是编程方便

mark

通过画图板的各种格式可以保存出不同的类型

mark

  • 深度

    深度即位数(比特数)

  • 位深:一个像素点所占的总位数,也叫像素深度、图像深度等

  • 位深 = 通道数 × 每个通道所占位数

  • 256色图:n位的像素点可以表示2^n种颜色,称2^n色图,n=8时为256色图

  • 8位RGB与8位图:前者的位数指每个通道所占的位数,后者指整个像素点共占的位数

  • 8位RGB是一个24位图,也称为真彩

    Mat对象构造函数

  • Mat()
    无参数构造方法

  • Mat(int rows, int cols, int type)
    创建行数为 rows,列数为 col,类型为 type 的图像

  • Mat(Size size, int type)
    创建大小为 size,类型为 type 的图像

  • Mat(int rows, int cols, int type, const Scalar& s)
    创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值s

  • Mat(Size size, int type, const Scalar& s)
    创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s

  • Mat(const Mat& m)
    将m赋值给新创建的对象,此处不会对图像数据进行复制,m和新对象共用图像数据,属于浅拷贝

  • Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
    创建行数为rows,列数为col,类型为type的图像,此构造函数不创建图像数据所需内存,而是直接使用data所指内存,图像的行步长由 step指定

  • Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
    创建大小为size,类型为type的图像,此构造函数不创建图像数据所需内存,而是直接使用data所指内存,图像的行步长由step指定

  • Mat(const Mat& m, const Range& rowRange, const Range& colRange)
    创建的新图像为m的一部分,具体的范围由rowRange和colRange指定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据

  • Mat(const Mat& m, const Rect& roi)
    创建的新图像为m的一部分,具体的范围roi指定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据

例如:Mat M(2,2,CV_8UC3, Scalar(0,0,255))
这些构造函数中,很多都涉及到类型type。type可以是CV_8UC1,CV_16SC1,CV_64FC4 等其中前两个参数分别表示行(row)跟列(column)、第三个CV_8UC3中的8表示每个通道占8位、U表示无符号、C表示Char类型、3表示通道数目是3,第四个参数是向量表示初始化每个像素值是多少,向量长度对应通道数目一致
如果你需要更多的通道数,需要用宏 CV_8UC(n) ,例如:
Mat M(3,2, CV_8UC(5)) 创建行数为 3,列数为 2,通道数为 5 的图像。

Mat对象常用方法

  • 部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分

    1
    2
    Mat A= imread("XXX");
    Mat B(A) // 只复制头信息,浅拷贝
  • 完全复制:如果想把Mat对象的头部和数据部分一起复制,可以通过如下两个API实现

    1
    2
    3
    Mat F = A.clone();  
    Mat G;
    A.copyTo(G);

Mat对象分为头部与数据部分,赋值操作和拷贝构造函数只会复制头部,要想用深拷贝只能使用clone() 、 copyTo(Mat dst,int type) !

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

int main(int argc,char **argv)
{
Mat src = imread("C:/Users/Tim/Desktop/Image/a.jpg");

if (src.empty())
{
std::cout << "load image filed" << std::endl;
return -1;
}

namedWindow("input window",CV_WINDOW_AUTOSIZE);
imshow("input window", src);

//通过ctreat函数创建
Mat m_c;
m_c.create(4, 4, CV_8UC2);
cout << m_c << endl;

//定义了一个dst对象的时候只是创建了Mat对象的头部
Mat dst;
dst = Mat(src.size(), src.type());
dst = Scalar(127, 0, 255);

namedWindow("output window", CV_WINDOW_AUTOSIZE);
imshow("output window", dst);

//都是深拷贝
dst = src.clone();
src.copyTo(dst);

//获取通道数
cvtColor(src, dst, CV_BGR2GRAY);
cout << "src.channels():" << src.channels() << endl;
cout << "dst.channels():" << dst.channels() << endl;

//获取首行像素指针
const uchar* firstRow = dst.ptr<uchar>(0);

//获取行像素、列像素
int row = dst.rows;
int col = dst.cols;

//创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化
Mat m(5, 5, CV_8UC3, Scalar(0, 0, 255));
cout << m << endl;

namedWindow("smail", CV_WINDOW_AUTOSIZE);
imshow("smail", m);


//定义小数组
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << C << endl;

waitKey(0);
return 0;
}

mark

这是创建的5*5的矩阵

mark

关于Scalar

查看源码opencv3源码, 发现Scalar做成了模板类,其中有如下构造函数:可以看到,Scalar是一个由长度为4的数组作为元素构成的结构体,Scalar最多可以存储四个值,没有提供的值默认是0。
Scalar常用的使用场景如下:

1
Mat M(7,7,CV_32FC2,Scalar(1,3));

上面的代码表示:创建一个2通道,且每个通道的值都为(1, 3),深度为32,7行7列的图像矩阵。CV_32F表示每个元素的值的类型为32位浮点数,C2表示通道数为2,Scalar(1,3)表示对矩阵每个元素都赋值为(1, 3),第一个通道中的值都是1,第二个通道中的值都是3.
dst = Scalar(127, 0, 255) 上述代码中颜色转换过来就是这样的:

mark

Mat对象使用-四个要点

  • 输出图像的内存是自动分配的

  • 使用OpenCV的C++接口,不需要考虑内存分配问题

  • 赋值操作和拷贝构造函数只会复制头部分

  • 使用clone与copyTo两个函数实现数据完全复制

    绘制形状与文字

    Point与Scalar

    Point表示2D平面上一个点,其成员就是 x,y 坐标

    Scalar表示四个元素的向量,表示 RGB 三个通道

    代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#include <iostream>
#include <opencv2\opencv.hpp>

using namespace cv;
using namespace std;

Mat bgImage;
void MyLines();
void MyRectangle();
void MyEllipse();
void MyCircle();
void MyPolyon();
void Random();
int main(int argc, char **argv){

bgImage = imread("C:\\Users\\Tim\\Desktop\\Image\\a.jpg");
if (bgImage.empty()){
cout << "load image filed..." << endl;
return -1;
}
MyLines();

MyRectangle();

MyEllipse();

MyCircle();

MyPolyon();

//绘制文字
//背景图、文字、起始点、字体(前提是系统必须支持设定的字体)、字体放大倍数、颜色、线粗、线条类型
putText(bgImage, "HelloWorld", Point(30, 50), CV_FONT_HERSHEY_COMPLEX, 2.0, Scalar(0, 0, 255), 2, 8);
namedWindow("src_window", CV_WINDOW_AUTOSIZE);
imshow("src_window", bgImage);

//Random();

waitKey(0);
return 0;
}

//绘制线条
void MyLines(){
Point p1 = Point(0, 0);
Point p2 = Point(410, 624);
Scalar color = Scalar(0, 0, 255);
//背景图、直线两头坐标、颜色、线粗、
//line(bgImage, p1, p2, color, 4, LINE_8);
//line(bgImage, p1, p2, color, 4, LINE_4);
line(bgImage, p1, p2, color, 4, LINE_AA);//LINE_AA是无锯齿
}

//绘制矩形
void MyRectangle(){
//起始坐标点,宽和高
Rect rect = Rect(120, 20, 200, 200);
Scalar color = Scalar(0, 255, 0);
rectangle(bgImage, rect, color, 2, LINE_AA);
}

//绘制椭圆
void MyEllipse(){
Scalar color = Scalar(255, 0, 0);
//背景图、中心点坐标、长轴和短轴、椭圆的倾斜度、(0-360就是绘制完整椭圆)、颜色、线粗、无锯齿
ellipse(bgImage, Point(bgImage.cols / 2, bgImage.rows / 2), Size(bgImage.cols / 4, bgImage.rows / 8), 45, 0, 180, color, 2, LINE_AA);
}

//绘制圆
void MyCircle(){
Scalar color = Scalar(255, 255, 0);
//背景图、圆心、半径
Point center = Point(bgImage.cols / 2, bgImage.rows / 2);
circle(bgImage, center, 150, color, 2, LINE_8);
}

//绘制多边形
void MyPolyon(){
//定义好多边形顶点的二维数组
Point pts[1][5];
pts[0][0] = Point(100, 100);
pts[0][1] = Point(120, 180);
pts[0][2] = Point(220, 200);
pts[0][3] = Point(150, 80);
pts[0][4] = Point(100, 100);

const Point* ppts[] = { pts[0] };
int npt[] = { 5 };
Scalar color = Scalar(0, 255, 255);
fillPoly(bgImage, ppts, npt, 1, color, 8);
}

//绘制随机线条
void Random(){
RNG rng(12345);//设置随机种子
Point pt1;
Point pt2;
Mat bg = Mat::zeros(bgImage.size(), bgImage.type());
namedWindow("random", CV_WINDOW_AUTOSIZE);

for (size_t i = 0; i <10000; i++)
{
//确保随机数的范围
pt1.x = rng.uniform(0, bg.cols);
pt2.x = rng.uniform(0, bg.cols);
pt1.y = rng.uniform(0, bg.rows);
pt2.y = rng.uniform(0, bg.rows);

waitKey(100);
Scalar color = Scalar(rng.uniform(0, 255), rng.uniform(0, 255), rng.uniform(0, 255));
line(bg, pt1, pt2, color, 1, 8);
imshow("random", bg);
}
}

mark

随机线条

赏

谢谢你请我喝咖啡

支付宝
微信
  • 本文作者: Tim
  • 本文链接: https://zouchanglin.cn/536300354.html
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 许可协议。转载请注明出处!
  • openCV
  • 图像处理

扫一扫,分享到微信

神奇的卷积核
图像亮度对比度调整
  1. 1. Mat对象与IplImage对象
  2. 2. Mat对象使用
    1. 2.1. 基本概念
      1. 2.1.1. 通道
      2. 2.1.2. 深度
    2. 2.2. Mat对象构造函数
    3. 2.3. Mat对象常用方法
      1. 2.3.1. 关于Scalar
    4. 2.4. Mat对象使用-四个要点
  3. 3. 绘制形状与文字
    1. 3.1. Point与Scalar
    2. 3.2. 代码
© 2017-2021 Tim
本站总访问量次 | 本站访客数人
  • 所有文章
  • 工具

tag:

  • 生活
  • Android
  • 索引
  • MySQL
  • 组件通信
  • Nginx
  • JavaSE
  • JUC
  • JavaWeb
  • 模板引擎
  • 前端
  • Linux
  • 计算机网络
  • Docker
  • C/C++
  • JVM
  • 上传下载
  • JavaEE
  • SpringCloud
  • Golang
  • Gradle
  • 网络安全
  • 非对称加密
  • IDEA
  • SpringBoot
  • Jenkins
  • 字符串
  • vim
  • 存储
  • 文件下载
  • Mac
  • Windows
  • NIO
  • RPC
  • 集群
  • 微服务
  • SSH
  • 配置中心
  • XML
  • Chrome
  • 压力测试
  • Git
  • 博客
  • 概率论
  • 排序算法
  • 分布式
  • 异常处理
  • 文件系统
  • 哈希
  • openCV
  • 栈
  • 回溯
  • SpringCore
  • 流媒体
  • rtmp
  • 面向对象
  • Vue
  • ElementUI
  • 软件工程
  • 异步
  • 自定义UI
  • ORM框架
  • 模块化
  • 交互式
  • Jsoup
  • Http Client
  • LRUCache
  • RabbitMQ
  • 消息通信
  • 服务解耦
  • 负载均衡
  • 权限
  • 多线程
  • 单例模式
  • Protobuf
  • 序列化
  • Python
  • m3u8
  • 堆
  • 二叉树
  • 自定义View
  • 观察者模式
  • 设计模式
  • 线程池
  • 动态扩容
  • 高可用
  • GC
  • ffmpeg
  • SpringMVC
  • REST
  • Redis
  • 缓存中间件
  • UML
  • Maven
  • Netty
  • 高性能网络
  • IPC通信
  • IO
  • Stream
  • 发布订阅
  • SQLite
  • Hash
  • 集合框架
  • 链表
  • Lambda
  • 汇编语言
  • 组件化
  • Router
  • 开发工具

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia-plus根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • 思维导图
  • PDF工具
  • 无损放大
  • 代码转图
  • HTTPS证书