OpenCV数据结构与基本绘图(Opencv3编程入门第4章)

OpenCV数据结构与基本绘图(Opencv3编程入门第4章)

第一节 基础图像容器Mat

  1. Mat是一个类,由两部分数据组成:矩阵头(包含矩阵尺寸、储存方法、储存地址等信息)和一个指向储存所有像素值的矩阵的指针。

  2. 不到万不得已,不应该进行大图像的复制,因为这会降低程序的运行速度。

  3. Mat类型对象的拷贝

Mat A, C;   //仅创建信息头部分
A = imread("1.jpg");     //为矩阵开辟内存空间
Mat B(A);    //使用拷贝构造函数
C= A;
//----------------------------------------------------------
//以上结果得到的A,B,C均指向同一个矩阵,对其中任意一个进行修改,另外两个的矩阵值也会随之变化。
//-----------------------------------------------------------

Mat F = A.clone();
Mat G;
A.copyTo(G);
//----------------------------------------------------------
//使用clone或者cloneTo可以复制矩阵本身,F,G,A分别指向不同的三个矩阵。
//-----------------------------------------------------------
  1. 小结:
  • OpenCV函数中输出图像的内存分配是自动完成的。
  • 使用OpenCV的C++接口时不需要考虑内存释放的问题。
  • 赋值运算符和拷贝构造函数只复制信息头(只复制指针)。
  • 使用函数clone()或者成员方法copyTo()来复制一幅图像的矩阵。
  1. 四种颜色系统
  • RGB
  • HSV和HLS把颜色分解为色调、饱和度和亮度/明度。
  • YCrCb在JPEG图像格式中广泛使用。
  • CIE Lab*是一种在感知上均匀的颜色空间,他适合用来度量两个颜色之间的距离。
  1. 创建Mat对象的几种方法
  • 使用Mat构造函数
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));
cout << M;
// 输出:[0, 0, 255, 0, 0, 255; 0, 0, 255, 0, 0, 255]

CV_8UC3表示使用8位的unsigned char类型,每个像素有三个元素组成三通道。
Scalar是个short类型的向量

  • 创建一个超过两维的矩阵:
int sz[3] = {2,2,2};
Mat L(3, sz, CV_8UC, Scalar::all(0));

第一个参数指定维度,然后传递一个指向数组的指针,包含每个维度的尺寸;后续的两个参数与之前的相同。

  • 为已存在的Ipllmage指针创建信息头
IplImage* img = cvLoadImage("1.jpg", 1);
Mat mtx(img);
  • 利用create()函数
M.create(4, 4, CV_8UC(2));

其中CV_8UC(2)表示2通道的8位unsigned char。
此创建方法不能为矩阵设置初值,只是在改变尺寸时重新为矩阵数据开辟内存而已。

  • 采用Matlab式的初始化方式
Mat E = Mat::eye(4, 4, CV_64F);
Mat O = Mat::ones(2,2,CV_32F);
Mat Z = Mat::zeros(3, 3, CV_8UC1);
  • 对小矩阵使用逗号分隔式初始化函数
Mat C = (Mat <double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
  • 为已存在的对象创建新信息头
 Mat RowClone = C.row(1).clone();
  • 先分配内存,在进行初始化赋值
Mat r = Mat(10, 3, CV_8UC3);
randu(r, Scalar::all(0), Scalar::all(255));     //在0 - 255之间取随机数进行赋值
  1. opencv的Mat格式化输出有很多样式,个人认为没有太大的作用,只要使用cout就可以了。

  2. 其他数据结构

  • 二维点:Point2f p(6,2);
  • 三维点:Point3f p3f(8, 2, 0);
  • 基于Mat类的std::vector
vector<float> v;
v.push_back(3);
v.push_back(5);
v.push_back(7);
  • 定义和输出std::vector点
vector<Point2f> points(20);
for (size_t i = 0; i < points.size(); ++i)
	points[i] = Point2f((float)(i * 5), (float)(i % 7));
cout << points;

二、常用数据结构和函数

  1. Point类
Point point;
point.x = 10;
point.y = 8;

Point point = Point(10, 8);

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

  1. 颜色的表示:Scalar类
    Scalar(a,b,c);三个参数分别为蓝色分量、绿色分量、红色分量。

  2. 尺寸的表示:Size类
    Size_<int>、Size2i、Size这三个类名等价。

  3. Rect类
    成员变量有x,y,width,height;成员函数有Size()返回Size;area()返回矩形的面积;contains(Point)判断点是否在矩形内;tl()返回左上角坐标;br()返回右下角坐标。

Rect rectShitf = rect + point;      //平移矩形
rect rectScale = rect + Size;		//缩放矩形
  1. 颜色空间转换
    void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0);
    src和dst分别表示输入图像和输出图像;code为颜色空间转换的标识符;第四个参数为目标图像的通道数,默认为0表示输出图像取输入图像的通道数。

基本图形的绘制

  • 头文件paint.h
#ifndef PAINT_H
#define PAINT_H
#include <opencv2/opencv.hpp>
using namespace cv;
void DrawEllipse(int x, int y, int width, int length, Mat img, float angle);
void DrawFilledCircle(Mat img, Point center, int radium);
#endif // PAINT_H
  • 源文件paint.cpp
#include "paint.h"
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
using namespace cv;


void DrawEllipse(int x, int y, int width, int length, Mat img, float angle) {
	/*
	x,y:椭圆中心的位置
	width,length:椭圆所在的矩形的大小
	img:Mat对象
	angle:椭圆旋转的角度
	*/
	int thickness = 2;
	int lineType = 8;

	ellipse( img,	//将输出的结果存放在img
		Point(x, y),	//椭圆中心的位置
		Size(width, length),   //椭圆所在的矩形的大小
		angle,   //椭圆旋转的角度
		0,		//椭圆扩展的弧度从0-360
		360,
		Scalar(255, 129, 0), 
		thickness,  //线宽
		lineType);	//线型
}


void DrawFilledCircle(Mat img, Point center, int radium) {
	/*
	center:圆心
	radium:半径
	*/
	int thickness = -1;
	int lineType = 8;

	circle(img,
		center,
		radium,
		Scalar(0, 0, 255),
		thickness,
		lineType);
}
  • 源文件main.cpp
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include "paint.h"
using namespace cv;


#define WINDOW_NAME1 "【绘制图1】"
#define WINDOW_NAME2 "【绘制图2】"
#define WINDOW_WIDTH 600

int main() {
	// 创建空白的Mat图像
	Mat atomImage = Mat::zeros(WINDOW_WIDTH, WINDOW_WIDTH, CV_8UC3);
	Mat rookImage = atomImage.clone();

	//线绘制出椭圆
	DrawEllipse(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2, WINDOW_WIDTH / 4, WINDOW_WIDTH / 16, atomImage, 90);
	DrawEllipse(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2, WINDOW_WIDTH / 4, WINDOW_WIDTH / 16, atomImage, 0);
	DrawEllipse(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2, WINDOW_WIDTH / 4, WINDOW_WIDTH / 16, atomImage, -45);
	DrawEllipse(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2, WINDOW_WIDTH / 4, WINDOW_WIDTH / 16, atomImage, 45);

	//绘制实心圆
	DrawFilledCircle(atomImage, Point(WINDOW_WIDTH / 2, WINDOW_WIDTH / 2), WINDOW_WIDTH / 32);

	imshow(WINDOW_NAME1, atomImage);
	moveWindow(WINDOW_NAME1, 0, 200);

	waitKey(0);
	return 0;
}

结果如下:
在这里插入图片描述

参考文献:OPenCV3编程入门 电子工业出版社 毛星云 冷雪飞等编著

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值