引言
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。
版权归原作者 J^T 所有, 如有侵权,请联系我们删除。