【Qt+opencv】Mat图像类型

文章目录


前言

在计算机视觉和图像处理领域,图像的表示和处理是最基本也是最重要的一部分。OpenCV(开源计算机视觉库)是一个广泛使用的计算机视觉库,它提供了丰富的函数和模块,用于图像处理和计算机视觉任务。在OpenCV中,图像数据通常存储在Mat对象中。Mat是OpenCV中的一个关键数据结构,它被设计用来存储实数或复数的多维矩阵,其中最常见的用途就是存储图像数据。

Qt是一个跨平台的C++图形用户界面应用程序开发框架,它为开发者提供了创建现代化GUI应用程序所需的所有功能。Qt的强大之处在于其高级的信号和槽机制、丰富的图形渲染能力以及对多线程和网络编程的支持。

本文将介绍如何在Qt环境下使用OpenCV的Mat对象进行图像处理。


图像与矩阵之间的关系

图像与矩阵之间有着密切的关系。在计算机视觉和图像处理中,图像通常被表示为矩阵。下面是一些关键点来帮助理解这种关系:

  1. 像素和矩阵元素:在数字图像中,每个像素对应于矩阵的一个元素。例如,一幅灰度图像可以被表示为一个二维矩阵,其中每个元素代表一个像素的灰度值。对于彩色图像(通常是RGB图像),它可以被表示为一个三维矩阵,其中每个元素是一个向量,包含红色、绿色和蓝色通道的强度值。

  2. 图像坐标和矩阵索引:图像的坐标系统通常定义为左上角为原点(0,0),向右为x轴,向下为y轴。这与矩阵的行和列索引相对应。例如,图像中的点(x,y)对应于矩阵中的元素(y,x)。

  3. 图像操作和矩阵操作:许多图像处理操作可以被视为矩阵操作。例如,图像的平移、旋转和缩放可以通过矩阵乘法来实现。滤波和卷积操作可以通过矩阵的元素级别操作来实现。

  4. 图像数据类型和矩阵数据类型:图像的数据类型通常决定了矩阵元素的数据类型。例如,如果图像是8位无符号整数类型,那么矩阵的元素也是8位无符号整数。

cv:Mat

cv::Mat的定义

cv::Mat是OpenCV库中的一个核心数据结构,它用于表示和存储图像和多维数组。在计算机视觉和图像处理中,我们通常会将图像视为一个矩阵,其中每个元素代表一个像素的值。cv::Mat就是这样一个矩阵,它可以存储各种类型的像素数据,包括灰度图像、彩色图像、深度图像等。

cpp 复制代码
class Mat
{
public:
	int flags;//这个成员变量包含了关于矩阵的信息,如:矩阵的标识、
								//数据是否连续、深度、通道数目等1。

    // 数组的维数,取值大于等于2
    int dims;

    // 数组的行数和列数(对于二维数组)
    int rows, cols;

    // 数组的数据
    uchar* data;

    // 其他成员...

    // 构造函数
    Mat();
    Mat(int rows, int cols, int type);
    Mat(Size size, int type);
    Mat(int ndims, const int* sizes, int type);

    // 其他方法...
};

dims:这个成员变量表示数组的维数,取值大于等于2。

rows, cols:对于二维数组(例如,图像),rows和cols分别表示数组的行数和列数。

data:这是一个指向实际数据的指针。这些数据可以是图像的像素值,也可以是其他类型的数据。

cv::Mat的数据类型

他的数据类型是:CV_8UC3,所以CV_8UC3是什么?
CV_8UC3是OpenCV中用于表示图像类型的一个常量。让我们来解析一下这个常量的含义:

  • CV:这是OpenCV的缩写,表示这是OpenCV库中的一个类型。
  • 8U:这表示图像的每个通道使用8位无符号整数来表示,取值范围是0-255。这是最常见的图像数据类型,因为它可以表示黑白和彩色图像的所有可能的亮度值。
  • C3:这表示图像有3个通道。对于彩色图像,这通常表示红色、绿色和蓝色三个通道。

我们可以这样创建一个cv::Mat类型:cv::Mat mat1(500,500,CV_8UC3);

cv::Mat像素读写

在OpenCV中,cv::Mat类提供了多种方法来读取和写入像素值。以下是一些常用的方法:

  1. 使用.at<>()函数:这是一个模板函数,可以用于读取和写入像素值。函数原型如下:

    cpp 复制代码
    template<typename _Tp> _Tp& cv::Mat::at(int i, int j);

    这个函数返回一个指向指定位置像素的引用,你可以用它来读取或修改像素值。例如,如果你有一个三通道的彩色图像img,你可以这样读取和修改一个像素:

    cpp 复制代码
    cv::Vec3b pixel = img.at<cv::Vec3b>(y, x); // 读取像素
    img.at<cv::Vec3b>(y, x) = pixel; // 写入像素
  2. 使用.ptr<>()函数:这个函数返回一个指向指定行的指针。函数原型如下:

    cpp 复制代码
    template<typename _Tp> _Tp* cv::Mat::ptr(int i);

    你可以用这个函数来访问图像的行,然后使用数组索引来访问特定的像素。例如:

    cpp 复制代码
    uchar* row = img.ptr<uchar>(y); // 获取行
    uchar pixel = row[x]; // 读取像素
    row[x] = pixel; // 写入像素
  3. 使用迭代器cv::Mat类提供了迭代器,可以用来遍历图像的所有像素。例如:

    cpp 复制代码
    cv::Mat_<cv::Vec3b>::iterator it = img.begin<cv::Vec3b>();
    cv::Mat_<cv::Vec3b>::iterator itend = img.end<cv::Vec3b>();
    for (; it != itend; ++it)
    {
        // 读取和修改像素
        cv::Vec3b pixel = *it;
        *it = pixel;
    }

图像局部操作

在OpenCV的cv::Mat类中,有多种方法可以用来选择和操作图像的特定区域。以下是一些主要的方法:

  1. 选择单行或单列 :你可以使用row(int i)col(int j)函数来选择单行或单列。这两个函数都返回一个新的cv::Mat对象,该对象与原始图像共享数据。例如:

    cpp 复制代码
    cv::Mat row = img.row(i); // 选择第i行
    cv::Mat col = img.col(j); // 选择第j列
  2. 选择多行或多列 :你可以使用rowRange(int startrow, int endrow)colRange(int startcol, int endcol)函数来选择多行或多列。这两个函数都返回一个新的cv::Mat对象,该对象与原始图像共享数据。例如:

    cpp 复制代码
    cv::Mat rows = img.rowRange(startrow, endrow); // 选择从startrow到endrow的多行
    cv::Mat cols = img.colRange(startcol, endcol); // 选择从startcol到endcol的多列
  3. 选择指定区域 :你可以使用cv::Mat::operator()(const Rect& roi)cv::Mat::operator()(const Range* ranges)来选择图像的一个特定区域。这两个操作符都返回一个新的cv::Mat对象,该对象与原始图像共享数据。例如:

    cpp 复制代码
    cv::Mat roi = img(Rect(x, y, width, height)); // 选择一个矩形区域
    cv::Mat submat = img(Range(row_start, row_end), Range(col_start, col_end)); // 选择一个子矩阵
  4. 取对角线元素 :你可以使用diag(int d)函数来获取矩阵的对角线元素。这个函数返回一个新的cv::Mat对象,该对象包含了原始矩阵的对角线元素。例如:

    cpp 复制代码
    cv::Mat diagonal = img.diag(0); // 获取主对角线元素

cv::Mat支持的运算

cv::Mat是OpenCV库中的一个核心数据结构,它支持多种数学和逻辑运算。以下是一些主要的运算:

  1. 元素级别的加法、减法、乘法和除法 :你可以使用cv::add(), cv::subtract(), cv::multiply(), 和 cv::divide()函数来进行这些运算。例如:

    cpp 复制代码
    cv::Mat result;
    cv::add(mat1, mat2, result); // 加法
    cv::subtract(mat1, mat2, result); // 减法
    cv::multiply(mat1, mat2, result); // 乘法
    cv::divide(mat1, mat2, result); // 除法
  2. 逻辑运算cv::Mat支持逻辑与、或、非等逻辑运算。例如:

    cpp 复制代码
    cv::Mat result;
    cv::bitwise_and(mat1, mat2, result); // 逻辑与
    cv::bitwise_or(mat1, mat2, result); // 逻辑或
    cv::bitwise_not(mat1, result); // 逻辑非
  3. 矩阵乘法 :你可以使用*运算符来进行矩阵乘法。例如:

    cpp 复制代码
    cv::Mat result = mat1 * mat2;
  4. 转置和求逆 :你可以使用cv::Mat::t()cv::Mat::inv()函数来进行矩阵的转置和求逆。例如:

    cpp 复制代码
    cv::Mat transposed = mat.t(); // 转置
    cv::Mat inverted = mat.inv(); // 求逆
  5. 统计运算cv::Mat支持一些统计运算,如求和(cv::sum()),求平均(cv::mean()),求最大值和最小值(cv::minMaxLoc())等。


总结

通过本文,我们了解了OpenCV的Mat对象以及如何在Qt环境下使用它进行图像处理。Mat对象是OpenCV中的核心组件,理解和掌握它对于进行有效的图像处理至关重要。同时,Qt作为一个强大的应用程序开发框架,与OpenCV的结合使得我们可以在强大的图形用户界面下进行图像处理,极大地提高了用户体验和开发效率。

然而,值得注意的是,虽然OpenCV和Qt都是非常强大的工具,但是要充分利用它们的功能并将它们结合起来使用,需要对这两个库有深入的理解。希望本文能为你提供一个良好的起点,帮助你开始在Qt环境下使用OpenCV进行图像处理的旅程。

相关推荐
lsx2024068 分钟前
SQL MID()
开发语言
Dream_Snowar11 分钟前
速通Python 第四节——函数
开发语言·python·算法
西猫雷婶13 分钟前
python学opencv|读取图像(十四)BGR图像和HSV图像通道拆分
开发语言·python·opencv
鸿蒙自习室13 分钟前
鸿蒙UI开发——组件滤镜效果
开发语言·前端·javascript
OpenCSG21 分钟前
CSGHub开源版本v1.2.0更新
人工智能
言、雲21 分钟前
从tryLock()源码来出发,解析Redisson的重试机制和看门狗机制
java·开发语言·数据库
weixin_5152024921 分钟前
第R3周:RNN-心脏病预测
人工智能·rnn·深度学习
Altair澳汰尔24 分钟前
数据分析和AI丨知识图谱,AI革命中数据集成和模型构建的关键推动者
人工智能·算法·机器学习·数据分析·知识图谱
AI视觉网奇1 小时前
人脸生成3d模型 Era3D
人工智能·计算机视觉
嵌入式科普1 小时前
十一、从0开始卷出一个新项目之瑞萨RA6M5串口DTC接收不定长
c语言·stm32·cubeide·e2studio·ra6m5·dma接收不定长