【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进行图像处理的旅程。

相关推荐
想成为高手4992 分钟前
生成式AI在教育技术中的应用:变革与创新
人工智能·aigc
YSGZJJ1 小时前
股指期货的套保策略如何精准选择和规避风险?
人工智能·区块链
Ajiang28247353041 小时前
对于C++中stack和queue的认识以及priority_queue的模拟实现
开发语言·c++
无脑敲代码,bug漫天飞1 小时前
COR 损失函数
人工智能·机器学习
幽兰的天空1 小时前
Python 中的模式匹配:深入了解 match 语句
开发语言·python
HPC_fac130520678162 小时前
以科学计算为切入点:剖析英伟达服务器过热难题
服务器·人工智能·深度学习·机器学习·计算机视觉·数据挖掘·gpu算力
Theodore_10224 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou4 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书4 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
小陈phd4 小时前
OpenCV从入门到精通实战(九)——基于dlib的疲劳监测 ear计算
人工智能·opencv·计算机视觉