目录
引言
一、Mat类详解
1. Mat类的基本结构
2. Mat类的数据类型
3. Mat类的创建与初始化
4. Mat类的使用技巧
二、OpenCV核心功能模块
1. 基本的图像读取与显示
2. 图像的保存
3. 矩阵操作
4. 等待键盘输入与销毁窗口
5. 命名窗口
三、图像处理模块
1. 色彩空间转换
2. 图像写入
3. 图像变换
4. 图像滤波
四、绘图与交互
1. 绘制基本图形
2. 文本绘制
3. 鼠标与键盘事件
4. 示例:在图像上绘制并响应鼠标事件
五、结论
引言
OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉和机器学习软件库,它提供了大量的图像处理、视频分析、对象检测等功能。本文将详细介绍OpenCV中常见的API以及绘图相关的知识,帮助开发者更好地理解和使用OpenCV。
一、Mat类详解
Mat类是OpenCV中C++版本的矩阵类,它替代了原来C版本的矩阵结构体CvMat和图像结构体IplImage。Mat类具有许多优势,特别是与STL(Standard Template Library)的兼容性很好,提供了许多类似于STL的操作,并且是一种高效的数据类型,对内存进行动态管理,无需用户手动管理内存。
1. Mat类的基本结构
Mat类定义于OpenCV的core.hpp中,主要包含两部分数据:
- 矩阵头(matrix header):这部分的大小是固定的,包含了矩阵的大小(行数和列数)、存储方式、矩阵存储的地址等信息。
- 数据指针(data pointer):一个指向矩阵包含像素值的指针,用于访问矩阵的实际数据。
Mat类的定义大致如下(简化版):
class CV_EXPORTS Mat {
public:
int flags; // 包含矩阵的多个标志位,如深度、通道数等
int dims; // 数组的维度,>= 2
int rows, cols; // 矩阵的行数和列数
uchar* data; // 指向数据的指针
int* refcount; // 指向引用计数器的指针
// 其他成员...
};
2. Mat类的数据类型
Mat类支持多种数据类型,这些数据类型决定了矩阵中元素的存储方式。常见的数据类型包括:
- CV_8U:8位无符号整数(0~255)
- CV_8S:8位有符号整数(-128~127)
- CV_16U:16位无符号整数(0~65535)
- CV_16S:16位有符号整数(-32768~32767)
- CV_32S:32位有符号整数
- CV_32F:32位浮点数
- CV_64F:64位浮点数
在OpenCV中,可以通过特定的模板类(如Mat_<uchar>
、Mat_<int>
等)或类型标识符(如CV_8UC1
、CV_32FC3
等)来指定Mat的数据类型。
3. Mat类的创建与初始化
Mat类可以通过多种方式创建和初始化:
-
使用构造函数:
Mat::Mat()
:默认构造函数,创建一个空的Mat对象。Mat::Mat(int rows, int cols, int type)
:指定行数、列数和类型创建Mat对象。Mat::Mat(Size size, int type)
:使用Size
结构体指定尺寸和类型创建Mat对象。Mat::Mat(const Mat& m)
:拷贝构造函数,创建一个与已有Mat对象相同的Mat对象(但注意,这种方式只是复制了矩阵头,数据是共享的)(浅拷贝)。
-
使用
create
函数:可以在不重新创建Mat对象的情况下改变其大小和类型。 -
使用其他函数:如
zeros
、ones
、eye
等,用于创建全零、全一或单位矩阵。
4. Mat类的使用技巧
- 元素访问:
- 使用
at
函数:M.at<type>(i, j)
,其中type
是元素的数据类型,i
和j
是行和列的索引。 - 使用迭代器:通过
MatIterator_
迭代器遍历矩阵元素。 - 使用指针:直接操作
data
指针访问矩阵数据(注意边界和步长)。
- 使用
- 矩阵操作:
- 支持多种数学运算,如加法、减法、乘法等。
- 支持矩阵变换,如转置、缩放、旋转等。
- 内存管理:
- Mat类自动管理内存,无需用户手动释放。
- 使用
clone
函数可以复制整个Mat对象(包括数据),避免数据共享问题。(深拷贝)
二、OpenCV核心功能模块
1. 基本的图像读取与显示
-
cv::imread:用于读取图像文件。其原型为
cv::Mat cv::imread(const String& filename, int flags = IMREAD_COLOR)
。其中,filename
是图像文件的路径,flags
是读取图像的方式,例如IMREAD_COLOR
表示以彩色模式读取图像,IMREAD_GRAYSCALE
表示以灰度模式读取图像。 -
cv::imshow:用于在窗口中显示图像。其原型为
void cv::imshow(const String& winname, InputArray mat)
。其中,winname
是窗口的名称,mat
是要显示的图像数据。
2. 图像的保存
- cv::imwrite:用于将图像写入文件。其原型为
bool cv::imwrite(const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>())
。其中,filename
是保存图像的路径,img
是要保存的图像数据,params
是保存图像时的一些可选参数。
3. 矩阵操作
- cv::Mat:是OpenCV中用于存储图像数据和其他多维数组的数据结构。提供了丰富的矩阵操作函数,如加法、减法、乘法、除法、归一化等。
4. 等待键盘输入与销毁窗口
- cv::waitKey:等待键盘输入。函数原型为
int cv::waitKey(int delay = 0)
。delay
参数表示等待时间(毫秒),如果设置为0,则表示无限等待。常用于在显示图像时等待用户按键。 - cv::destroyAllWindows:销毁所有由OpenCV创建的窗口。
5. 命名窗口
- cv::namedWindow:用于创建窗口并指定窗口类型。函数原型为
void cv::namedWindow(const String& winname, int flags = WINDOW_AUTOSIZE)
。winname
是窗口名称,flags
用于指定窗口类型,如WINDOW_AUTOSIZE
表示窗口大小自动调整。
三、图像处理模块
1. 色彩空间转换
- cv::cvtColor:用于图像的色彩空间转换。其原型为
void cv::cvtColor(InputArray src, OutputArray dst, int code, int dstCn = 0)
。其中,src
是输入图像,dst
是输出图像,code
是转换代码,如COLOR_BGR2GRAY
表示将BGR图像转换为灰度图像。
2. 图像写入
- cv::imwrite:用于将图像写入文件。函数原型为
bool cv::imwrite(const String& filename, InputArray img, const std::vector<int>& params = std::vector<int>())
。filename
是输出文件的路径,img
是要写入的图像数据。
3. 图像变换
-
cv::resize:用于改变图像的大小。支持多种插值方法,如线性插值、立方插值等。
-
cv::warpAffine和cv::warpPerspective:分别用于图像的仿射变换和透视变换。
4. 图像滤波
- cv::blur和cv::GaussianBlur:分别用于图像的均值模糊和高斯模糊。
四、绘图与交互
1. 绘制基本图形
-
cv::line:用于绘制直线。其原型为
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
是线条的粗细。 -
cv::rectangle:用于绘制矩形。其原型为
void cv::rectangle(InputOutputArray img, Point pt1, Point pt2, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0)
。其中,pt1
和pt2
分别是矩形的左上顶点和右下顶点。 -
cv::circle:用于绘制圆形。其原型为
void cv::circle(InputOutputArray img, Point center, int radius, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0)
。其中,center
是圆心的坐标,radius
是圆的半径。 -
cv::ellipse:用于绘制椭圆。其原型为
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)
。其中,center
是椭圆的圆心坐标,axes
是椭圆的长轴和短轴的长度,angle
是椭圆的旋转角度。 -
cv::polylines:用于绘制多边形。其原型为
void cv::polylines(InputOutputArray img, InputArrayOfArrays pts, bool isClosed, const Scalar& color, int thickness = 1, int lineType = LINE_8, int shift = 0)
。其中,pts
是多边形的顶点坐标,isClosed
表示多边形是否闭合。
2. 文本绘制
- cv::putText:用于在图像上绘制文本。其原型为
void cv::putText(InputOutputArray img, const String& text, Point org, int fontFace, double fontScale, const Scalar& color, int thickness = 1, int lineType = LINE_8, bool bottomLeftOrigin = false)
。其中,img
是绘制文本的图像,text
是要绘制的文本字符串,org
是文本左下角的坐标(如果bottomLeftOrigin
为false
,则为左下角的坐标,否则为基线的起点),fontFace
是字体的类型,fontScale
是字体大小的缩放比例,color
是文本的颜色,thickness
是文本的线条粗细。
3. 鼠标与键盘事件
OpenCV提供了创建窗口并响应鼠标和键盘事件的功能,这在交互式应用中非常有用。你可以使用cv::namedWindow
来创建一个窗口,然后使用cv::setMouseCallback
和cv::setKeyboardCallback
来分别设置鼠标和键盘的回调函数。
- cv::namedWindow:创建一个窗口。
- cv::setMouseCallback:为指定的窗口设置鼠标回调函数。
- cv::setKeyboardCallback:为指定的窗口设置键盘回调函数。
4. 示例:在图像上绘制并响应鼠标事件
#include <opencv2/opencv.hpp>
void onMouse(int event, int x, int y, int flags, void* param) {
cv::Mat* image = (cv::Mat*)param;
if (event == cv::EVENT_LBUTTONDOWN) {
cv::circle(*image, cv::Point(x, y), 5, cv::Scalar(0, 255, 0), -1);
}
}
int main() {
cv::Mat image = cv::imread("path_to_image.jpg");
if (image.empty()) {
std::cerr << "Could not read the image" << std::endl;
return 1;
}
cv::namedWindow("Image Window", cv::WINDOW_AUTOSIZE);
cv::setMouseCallback("Image Window", onMouse, &image);
while (true) {
cv::imshow("Image Window", image);
if (cv::waitKey(20) >= 0) break;
}
return 0;
}
在这个示例中,我们创建了一个窗口并在其中显示一张图像。通过cv::setMouseCallback
设置了一个鼠标回调函数onMouse
,该函数会在鼠标左键点击时在图像上绘制一个绿色的圆点。
五、结论
OpenCV提供了丰富的API用于图像处理、图像分析以及绘图等任务。通过本文的介绍,你应该对OpenCV中常见的API以及绘图相关的知识有了更深入的了解。希望这些信息能够帮助你在实际的项目中更加高效地利用OpenCV。