0


OPenCV高级编程——OpenCV常见的API及绘图知识详解

引言

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中,主要包含两部分数据:

  1. 矩阵头(matrix header):这部分的大小是固定的,包含了矩阵的大小(行数和列数)、存储方式、矩阵存储的地址等信息。
  2. 数据指针(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类可以通过多种方式创建和初始化:

  1. 使用构造函数:- 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对象(但注意,这种方式只是复制了矩阵头,数据是共享的)(浅拷贝)。
  2. 使用create函数:可以在不重新创建Mat对象的情况下改变其大小和类型。
  3. 使用其他函数:如zerosoneseye等,用于创建全零、全一或单位矩阵。

4. Mat类的使用技巧

  1. 元素访问: - 使用at函数:M.at<type>(i, j),其中type是元素的数据类型,ij是行和列的索引。- 使用迭代器:通过MatIterator_迭代器遍历矩阵元素。- 使用指针:直接操作data指针访问矩阵数据(注意边界和步长)。
  2. 矩阵操作: - 支持多种数学运算,如加法、减法、乘法等。- 支持矩阵变换,如转置、缩放、旋转等。
  3. 内存管理: - 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::warpAffinecv::warpPerspective:分别用于图像的仿射变换和透视变换。

4. 图像滤波

  • cv::blurcv::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是绘制图形的载体,pt1pt2是线段的起点和终点,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)。其中,pt1pt2分别是矩形的左上顶点和右下顶点。
  • 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是文本左下角的坐标(如果bottomLeftOriginfalse,则为左下角的坐标,否则为基线的起点),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。


本文转载自: https://blog.csdn.net/weixin_62621696/article/details/140824866
版权归原作者 J^T 所有, 如有侵权,请联系我们删除。

“OPenCV高级编程——OpenCV常见的API及绘图知识详解”的评论:

还没有评论