OpenCV4X学习—核心模块Core

libopencv_core4130.dll.a:

核心模块,定义了基本数据结构,如多维数组Mat,还包含了其他模块常用的基本函数,为整个 OpenCV 库提供基础支持。

功能与用途

图像存储:cv::Mat 最常见的用途是存储图像数据。无论是灰度图像(单通道)、彩色图像(如 RGB 三通道或 RGBA 四通道),还是多光谱图像,都可以用 cv::Mat 来表示。例如,一幅 8 位灰度图像可以存储为一个 cv::Mat,其数据类型为 CV_8U(8 位无符号整数),每个元素对应图像中的一个像素值。

矩阵运算:除了图像数据,cv::Mat 也可用于一般的矩阵运算。它支持各种数学运算,如加法、减法、乘法、除法等,使得在处理图像或其他数据矩阵时非常方便。例如,在图像融合、滤波等操作中,经常需要对图像矩阵进行算术运算。

数据结构特点

头与数据分离:cv::Mat 采用了一种头与数据分离的设计。矩阵头(包含矩阵的尺寸、数据类型、引用计数等信息)和实际的数据存储区域是分开的。这样的设计使得矩阵的复制和传递变得高效,因为复制矩阵时只需复制矩阵头,而无需复制大量的数据,只有在真正需要修改数据时才会进行数据的深拷贝,这一机制被称为引用计数机制。

灵活的数据存储方式:cv::Mat 可以存储不同类型的数据,通过模板化的数据类型标识符来指定。常见的数据类型包括 CV_8U、CV_8S(8 位有符号整数)、CV_16U、CV_16S、CV_32S(32 位有符号整数)、CV_32F(32 位浮点数)、CV_64F(64 位浮点数)等。此外,它还支持多通道数据存储,例如,彩色图像的 RGB 三个通道可以存储在一个 cv::Mat 中,每个元素是一个包含三个值的向量,分别对应红、绿、蓝通道的值。

主要成员函数

创建与初始化:

cv::Mat::Mat(int rows, int cols, int type):通过指定行数、列数和数据类型来创建矩阵。例如,cv::Mat image(100, 100, CV_8UC3) 创建一个 100x100 的三通道 8 位无符号整数矩阵,常用于存储彩色图像。

cv::Mat::Mat(const cv::Size& size, int type):使用 cv::Size 结构体来指定矩阵的尺寸,功能与上述类似。

cv::Mat::ones(int rows, int cols, int type) 和 cv::Mat::zeros(int rows, int cols, int type):分别创建一个全为 1 或全为 0 的矩阵。

元素访问:

at<>() 模板函数:用于访问矩阵中的元素。例如,对于一个单通道 8 位无符号整数矩阵 mat,可以通过 mat.at(i, j) 来访问第 i 行第 j 列的元素;对于多通道矩阵,如 RGB 图像矩阵,可以使用 mat.atcv::Vec3b(i, j)[0] 来访问第 i 行第 j 列像素的红色通道值。

属性获取:

rows 和 cols 成员变量:分别返回矩阵的行数和列数。

type() 函数:返回矩阵的数据类型标识符,通过该标识符可以判断矩阵的数据类型和通道数。

channels() 函数:返回矩阵的通道数。

操作函数:

clone() 函数:创建一个与原矩阵完全相同的深拷贝,包括矩阵头和数据。

copyTo() 函数:将当前矩阵的数据复制到另一个矩阵中,可以选择指定感兴趣区域(ROI)进行复制。

在 OpenCV 中的应用场景

图像处理:在几乎所有的图像处理算法中都离不开 cv::Mat。例如,图像滤波算法(如高斯滤波、中值滤波)需要读取和修改 cv::Mat 中的像素值;图像变换(如仿射变换、透视变换)则是对 cv::Mat 进行几何操作;图像特征提取(如 SIFT、SURF、ORB 等)过程中,cv::Mat 用于存储图像以及提取到的特征描述符。

计算机视觉任务:在目标检测、识别、跟踪等计算机视觉任务中,cv::Mat 用于存储输入图像、处理中间结果以及输出检测或识别结果。例如,在基于 Haar 级联的人脸检测中,输入的图像首先被读取到一个 cv::Mat 中,经过一系列的处理后,检测到的人脸区域信息也可以存储在 cv::Mat 或基于 cv::Mat 的数据结构中。

bash 复制代码
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <Qdebug>
#include <opencv2/opencv.hpp>

// 交换两个Mat矩阵的示例函数
void exampleSwap() {
    // 创建一个3x3的单精度浮点型矩阵a,初始值全为1
    cv::Mat a = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵b,初始值全为0
    cv::Mat b = cv::Mat::zeros(3, 3, CV_32F);
    // 交换矩阵a和b
    cv::swap(a, b);
    // 判断交换后a是否全为0
    bool aIsAllZeros = cv::countNonZero(a - cv::Mat::zeros(3, 3, CV_32F)) == 0;
    // 判断交换后b是否全为1
    bool bIsAllOnes = cv::countNonZero(b - cv::Mat::ones(3, 3, CV_32F)) == 0;
    // 输出交换后a是否全为0的结果
    qDebug() << "After swap, a is all zeros: " << aIsAllZeros;
    // 输出交换后b是否全为1的结果
    qDebug() << "After swap, b is all ones: " << bIsAllOnes;
}

// 边界插值的示例函数
void exampleBorderInterpolate() {
    int p = 5; // 要插值的位置
    int len = 10; // 边界长度
    int borderType = cv::BORDER_CONSTANT; // 边界类型,这里是常量边界
    // 进行边界插值计算
    int result = cv::borderInterpolate(p, len, borderType);
    // 输出边界插值的结果
    qDebug() << "Border interpolate result: " << result;
}

// 复制并添加边界的示例函数
void exampleCopyMakeBorder() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储添加边界后的结果矩阵
    int top = 1, bottom = 1, left = 1, right = 1; // 上下左右要添加的边界宽度
    int borderType = cv::BORDER_CONSTANT; // 边界类型,常量边界
    cv::Scalar value(0); // 常量边界的值
    // 对src矩阵进行复制并添加边界操作
    cv::copyMakeBorder(src, dst, top, bottom, left, right, borderType, value);
    // 输出添加边界后的矩阵大小
    qDebug() << "Copied and bordered matrix size: " << dst.rows << " x " << dst.cols;
}

// 矩阵加法的示例函数
void exampleAdd() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储加法结果的矩阵
    // 对src1和src2进行矩阵加法操作
    cv::add(src1, src2, dst);

    // 输出加法结果的提示信息
    qDebug() << "Addition result:";
    // 遍历并输出结果矩阵dst的每个元素
    for(int i = 0; i < dst.rows; ++i) {
        for(int j = 0; j < dst.cols; ++j) {
            qDebug() << dst.at<float>(i, j);
        }
    }
}

// 重载QDebug操作符,用于输出cv::Mat矩阵
QDebug operator<<(QDebug debug, const cv::Mat& mat) {
    // 输出矩阵的基本信息,包括行数和列数
    debug << "cv::Mat(" << mat.rows << ", " << mat.cols << ") {";
    for(int i = 0; i < mat.rows; ++i) {
        for(int j = 0; j < mat.cols; ++j) {
            // 如果矩阵类型是单精度浮点型
            if(mat.type() == CV_32F) {
                // 输出矩阵元素
                debug << mat.at<float>(i, j) << " ";
            }
            // 如果矩阵类型是8位无符号整型
            else if(mat.type() == CV_8U) {
                // 输出矩阵元素
                debug << (int)mat.at<uchar>(i, j) << " ";
            }
            // 可根据需要添加更多数据类型的处理
        }
        // 换行
        debug << "\n";
    }
    // 输出矩阵结束标志
    debug << "}";
    return debug;
}

// 重载QDebug操作符,用于输出cv::Scalar
QDebug operator<<(QDebug debug, const cv::Scalar& scalar) {
    // 输出Scalar的开始标志
    debug << "cv::Scalar(";
    for(int i = 0; i < 4; ++i) {
        // 输出Scalar的元素
        debug << scalar.val[i];
        if(i < 3) {
            // 如果不是最后一个元素,输出逗号和空格
            debug << ", ";
        }
    }
    // 输出Scalar的结束标志
    debug << ")";
    return debug;
}

// 矩阵减法的示例函数
void exampleSubtract() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储减法结果的矩阵
    // 对src1和src2进行矩阵减法操作
    cv::subtract(src1, src2, dst);
    // 输出减法结果
    qDebug() << "Subtraction result: " << dst;
}

// 矩阵乘法的示例函数
void exampleMultiply() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储乘法结果的矩阵
    double scale = 2; // 乘法的缩放因子
    // 对src1和src2进行矩阵乘法操作,并应用缩放因子
    cv::multiply(src1, src2, dst, scale);
    // 输出乘法结果
    qDebug() << "Multiplication result: " << dst;
}

// 矩阵除法的示例函数
void exampleDivide() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储除法结果的矩阵
    double scale = 2; // 除法的缩放因子
    // 对src1和src2进行矩阵除法操作,并应用缩放因子
    cv::divide(src1, src2, dst, scale);
    // 输出除法结果
    qDebug() << "Division result: " << dst;
}

// 缩放并加法的示例函数
void exampleScaleAdd() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储缩放并加法结果的矩阵
    double alpha = 2; // 缩放因子
    // 对src1进行缩放后与src2相加
    cv::scaleAdd(src1, alpha, src2, dst);
    // 输出缩放并加法的结果
    qDebug() << "Scale and add result: " << dst;
}

// 加权加法的示例函数
void exampleAddWeighted() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储加权加法结果的矩阵
    double alpha = 0.5, beta = 0.5, gamma = 0; // 加权系数
    // 对src1和src2进行加权加法操作
    cv::addWeighted(src1, alpha, src2, beta, gamma, dst);
    // 输出加权加法的结果
    qDebug() << "Add weighted result: " << dst;
}

// 转换、缩放并取绝对值的示例函数
void exampleConvertScaleAbs() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为0.5
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F) * 0.5;
    cv::Mat dst; // 用于存储转换、缩放并取绝对值结果的矩阵
    double alpha = 255, beta = 0; // 缩放因子和偏移量
    // 对src进行转换、缩放并取绝对值操作
    cv::convertScaleAbs(src, dst, alpha, beta);
    // 输出转换、缩放并取绝对值的结果
    qDebug() << "Convert scale and abs result: " << dst;
}

// 查找表操作的示例函数
void exampleLUT() {
    // 创建一个3x3的8位无符号整型矩阵src,初始值全为128
    cv::Mat src = cv::Mat::ones(3, 3, CV_8U) * 128;
    // 创建一个256x1的8位无符号整型查找表lut,初始值全为0
    cv::Mat lut = cv::Mat::zeros(256, 1, CV_8U);
    for (int i = 0; i < 256; ++i) {
        // 填充查找表,将每个值映射为255 - i
        lut.at<uchar>(i) = 255 - i;
    }
    cv::Mat dst; // 用于存储查找表操作结果的矩阵
    // 对src应用查找表lut
    cv::LUT(src, lut, dst);
    // 输出查找表操作的结果
    qDebug() << "LUT result: " << dst;
}

// 计算矩阵元素总和的示例函数
void exampleSum() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    // 计算src矩阵元素的总和
    cv::Scalar result = cv::sum(src);
    // 输出矩阵元素总和
    qDebug() << "Sum of elements: " << result;
}

// 判断矩阵是否有非零元素的示例函数
void exampleHasNonZero() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    // 判断src矩阵是否有非零元素
    bool result = cv::hasNonZero(src);
    // 输出判断结果
    qDebug() << "Has non - zero elements: " << result;
}

// 统计矩阵中非零元素个数的示例函数
void exampleCountNonZero() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    // 统计src矩阵中非零元素的个数
    int result = cv::countNonZero(src);
    // 输出非零元素的个数
    qDebug() << "Count of non - zero elements: " << result;
}

// 查找矩阵中非零元素索引的示例函数
void exampleFindNonZero() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat idx; // 用于存储非零元素索引的矩阵
    // 查找src矩阵中非零元素的索引
    cv::findNonZero(src, idx);
    // 输出非零元素的索引
    qDebug() << "Indices of non - zero elements: " << idx;
}

// 计算矩阵元素平均值的示例函数
void exampleMean() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    // 计算src矩阵元素的平均值
    cv::Scalar result = cv::mean(src);
    // 输出矩阵元素的平均值
    qDebug() << "Mean of elements: " << result;
}

// 计算矩阵元素均值和标准差的示例函数
void exampleMeanStdDev() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat mean, stddev; // 用于存储均值和标准差的矩阵
    // 计算src矩阵元素的均值和标准差
    cv::meanStdDev(src, mean, stddev);
    // 输出均值和标准差
    qDebug() << "Mean: " << mean << " Std Dev: " << stddev;
}

// 计算矩阵范数的示例函数
void exampleNorm() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 计算src1矩阵的范数
    double result = cv::norm(src1);
    // 输出矩阵的范数
    qDebug() << "Norm of matrix: " << result;
}

// 计算两个矩阵峰值信噪比(PSNR)的示例函数
void examplePSNR() {
    // 创建一个3x3的单精度浮点型矩阵src1,初始值全为1
    cv::Mat src1 = cv::Mat::ones(3, 3, CV_32F);
    // 创建一个3x3的单精度浮点型矩阵src2,初始值全为1
    cv::Mat src2 = cv::Mat::ones(3, 3, CV_32F);
    // 计算src1和src2矩阵的峰值信噪比
    double result = cv::PSNR(src1, src2);
    // 输出两个矩阵的峰值信噪比
    qDebug() << "PSNR between two matrices: " << result;
}

// 矩阵归一化的示例函数
void exampleNormalize() {
    // 创建一个3x3的单精度浮点型矩阵src,初始值全为1
    cv::Mat src = cv::Mat::ones(3, 3, CV_32F);
    cv::Mat dst; // 用于存储归一化结果的矩阵
    double alpha = 0, beta = 1; // 归一化的范围
    int norm_type = cv::NORM_MINMAX; // 归一化类型,这里是最小 - 最大归一化
    // 对src矩阵进行归一化操作
    cv::normalize(src, dst, alpha, beta, norm_type);
    // 输出归一化后的矩阵
    qDebug() << "Normalized matrix: " << dst;
}
int maintest() {
    // 调用各个示例函数
    exampleSwap();
    exampleBorderInterpolate();
    exampleCopyMakeBorder();
    exampleAdd();
    exampleSubtract();
    exampleMultiply();
    exampleDivide();
    exampleScaleAdd();
    exampleAddWeighted();
    exampleConvertScaleAbs();
    exampleLUT();
    exampleSum();
    exampleHasNonZero();
    exampleCountNonZero();
    exampleFindNonZero();
    exampleMean();
    exampleMeanStdDev();
    exampleNorm();
    examplePSNR();
    exampleNormalize();

    return 0;
}

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    maintest();

}

MainWindow::~MainWindow()
{
    delete ui;
}
相关推荐
刘立军7 小时前
如何选择FAISS的索引类型
人工智能·算法·架构
@zulnger7 小时前
python 学习笔记(多线程和多进程)
笔记·python·学习
gravity_w7 小时前
Hugging Face使用指南
人工智能·经验分享·笔记·深度学习·语言模型·nlp
凉、介7 小时前
SylixOS 中的 Unix Socket
服务器·c语言·笔记·学习·嵌入式·sylixos
好奇龙猫7 小时前
【人工智能学习-AI-MIT公开课第 19. 架构:GPS、SOAR、包容架构】
人工智能·学习·架构
特立独行的猫a8 小时前
告别碎片化笔记:基于n8n-mcp的AI写作助手实战
人工智能·笔记·ai写作·n8n·n8n-mcp
oioihoii8 小时前
构建高并发AI服务网关:C++与gRPC的工程实践
开发语言·c++·人工智能
范桂飓8 小时前
大模型分布式训练框架 Megatron-LM
人工智能·分布式
星云数灵8 小时前
大模型高级工程师考试练习题6
人工智能·大模型·大模型工程师·阿里云大模型aca·阿里云大模型工程师acp·大模型acp考试题库·acp认证