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

相关推荐
羊小猪~~几秒前
数据结构C语言描述2(图文结合)--有头单链表,无头单链表(两种方法),链表反转、有序链表构建、排序等操作,考研可看
c语言·数据结构·c++·考研·算法·链表·visual studio
撞南墙者3 分钟前
OpenCV自学系列(1)——简介和GUI特征操作
人工智能·opencv·计算机视觉
OCR_wintone4214 分钟前
易泊车牌识别相机,助力智慧工地建设
人工智能·数码相机·ocr
binishuaio6 分钟前
Java 第11天 (git版本控制器基础用法)
java·开发语言·git
zz.YE8 分钟前
【Java SE】StringBuffer
java·开发语言
就是有点傻12 分钟前
WPF中的依赖属性
开发语言·wpf
洋24021 分钟前
C语言常用标准库函数
c语言·开发语言
进击的六角龙22 分钟前
Python中处理Excel的基本概念(如工作簿、工作表等)
开发语言·python·excel
wrx繁星点点23 分钟前
状态模式(State Pattern)详解
java·开发语言·ui·设计模式·状态模式
王哈哈^_^26 分钟前
【数据集】【YOLO】【VOC】目标检测数据集,查找数据集,yolo目标检测算法详细实战训练步骤!
人工智能·深度学习·算法·yolo·目标检测·计算机视觉·pyqt