• opencv笔记 -- 核心功能模块(Mat)


    笔者之前零零碎碎地用过一些opencv,但是一直没有足够详尽的了解,正巧刷到了opencv的tutorial,仅以此记录。
    网址:link

    Mat - 基本的图像容器

    在这里插入图片描述
    一张普通的图片,如果想让计算机也能读得懂的话,我们需要把他转换成矩阵格式,也就是上图中的数字部分。使用Opencv的主要重点就是操作和处理这些数据。那么第一步就是如何存储和处理图片。

    在opencv中使用mat来存储图像,且不需要手动分配其内存或在不需要时释放它。大多数OpenCV函数将自动分配其输出数据。如果您传递一个已经存在的Mat对象,它已经为矩阵分配了所需的空间,那么它将被重用。换句话说,我们在任何时候都只使用执行任务所需的内存。

    为了避免对较大图像的不必要复制,opencv使用了一个引用计数系统,让每个mat对象都有自己的头,但是一个矩阵可以在两个mat对象之间共享,通过让它们的矩阵指针指向相同的地址。此外,复制操作符只复制头文件和指向大矩阵的指针,而不复制数据本身。

    Mat A, C; // creates just the header parts
    A = imread(argv[1], IMREAD_COLOR); // here we'll know the method used (allocate matrix)
     
    Mat B(A); // Use the copy constructor
     
    C = A; // Assignment operator
    

    上面的所有的对象都指向了同一个单一的数据矩阵,并且其中任意一个发生了改变都会影响其他的。实际上不同的对象仅会对同一个根本数据提供不同的入口。然而,它们的标题部分是不同的。真正有趣的部分是,您可以创建仅引用完整数据的一部分的头。例如,要在图像中创建感兴趣的区域(ROI),只需创建带有新边界的新标题:

    Mat D (A, Rect(10, 10, 100, 100) ); // using a rectangle
    Mat E = A(Range::all(), Range(1,3)); // using row and column boundaries
    

    如果矩阵属于不同的Mat对象,最后一个使用该矩阵的对象负责清理该矩阵。如果有复制图片的需求,那么可以使用cv::Mat::clone() 和cv::Mat::copyTo()功能。

    Mat F = A.clone();
    Mat G;
    A.copyTo(G);
    

    对F和G的修改不会对A造成任何影响。以下是一些总结的tips

    • 输出的图片分瓶是自动完成的。
    • 无需担心内存管理。
    • 赋值操作和复制构造只复制了头部。
    • 一个图片的根本矩阵可以使用clone和copyto功能进行复制。

    存储方法

    我们可以使用颜色空间和数据类型来存储像素的值。颜色空间指的是我们如何组合颜色组件来编码给定的颜色。最简单的一种是灰度,我们可以使用的颜色是黑色和白色。这些组合使我们能够创造出许多灰色阴影。

    彩色方案可以被分成三到四个基础颜色组合(三原色)。最流行的组合是RGB,主要是因为我们的眼睛就是以此为基础来组成颜色的。此外,透明度alpha(A)也会被添加进来。(0代表完全透明,255代表完全不透明)。

    但是不同的颜色系统的优势各不相同:

    • RGB是最常见的,因为我们的眼睛使用类似的东西,但请记住,OpenCV标准显示系统使用BGR色彩空间(红色和蓝色通道交换位置)来组合颜色。
    • HSV和HLS将颜色分解成它们的色调、饱和度和值/亮度组件,这是我们描述颜色的一种更自然的方式。例如,您可以忽略最后一个组件,使您的算法对输入图像的光照条件不那么敏感。
    • 流行的JPEG图像格式使用YCrCb。
    • CIE Lab*是一个感知上一致的色彩空间,如果你需要测量一种给定颜色到另一种颜色的距离,它会派上用场。

    创造一个Mat对象

    以下是创建一个Mat对象的方法:

    • 默认构造
     Mat M(2,2, CV_8UC3, Scalar(0,0,255));
     cout << "M = " << endl << " " << M << endl << endl;
    

    在这里插入图片描述

    对于二维多通道图像,我们首先需要定义他们的大小,行数和列数。然后需要明确用来存储这些元素的数据类型和每个矩阵点的通道数。

    CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number]
    

    举个例子,CV_8UC3代表我们使用unsigned char类型,8bit长且每个像素都有三个char类型来组成三个通道。通道最多只有四个。标量是一个四元素短向量。指定它,您可以用自定义值初始化所有矩阵点。如果需要更多类型,可以使用上面的宏创建类型,在括号中设置通道号,如下所示。

    • 使用c/c++队列并通过构造器进行初始化。
     int sz[3] = {2,2,2};
     Mat L(3,sz, CV_8UC(1), Scalar::all(0));
    

    上面的例子展示了如何创建一个二维以上的矩阵。指定它的维度,然后传递一个包含每个维度大小的指针,其余部分保持不变。

    • cv::Mat::create功能
     M.create(4,4, CV_8UC(2));
     cout << "M = "<< endl << " " << M << endl << endl;
    

    在这里插入图片描述
    你无法通过这个构造器来初始化这个矩阵,尽在新的大小不符合原来的大小时,才会重新分配数据内存。

    • MATLAB style 初始化: cv::Mat::zeros , cv::Mat::ones , cv::Mat::eye
     Mat E = Mat::eye(4, 4, CV_64F);
     cout << "E = " << endl << " " << E << endl << endl;
     Mat O = Mat::ones(2, 2, CV_32F);
     cout << "O = " << endl << " " << O << endl << endl;
     Mat Z = Mat::zeros(3,3, CV_8UC1);
     cout << "Z = " << endl << " " << Z << endl << endl;
    

    在这里插入图片描述

    • 对于小的矩阵,你可以使用逗号来区分初始化器
     Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
     cout << "C = " << endl << " " << C << endl << endl;
    
     C = (Mat_<double>({0, -1, 0, -1, 5, -1, 0, -1, 0})).reshape(3);
     cout << "C = " << endl << " " << C << endl << endl;
    

    在这里插入图片描述

    • 为一个已经存在的Mat对象创造一个新的头部并使用 cv::Mat::clone or cv::Mat::copyTo
     Mat RowClone = C.row(1).clone();
     cout << "RowClone = " << endl << " " << RowClone << endl << endl;
    

    在这里插入图片描述

    note:
    你可以使用**cv::randu()**功能来随机填充一个矩阵,但是需要给出一个最小和最大值的限制。

     Mat R = Mat(3, 2, CV_8UC3);
     randu(R, Scalar::all(0), Scalar::all(255));
    

    输出格式

    原文写得挺好的,直接贴上来。
    在这里插入图片描述

    其他的常见输出

    在这里插入图片描述

    总结

    本文主要介绍了一下如何在opencv中进行存储,以及相应的一些操作,如复制,构造等。
    在笔者的实际使用过程中,需要格外注意opencv的操作耗时问题,尤其是cv::imread操作。

  • 相关阅读:
    windows下修改mysql的max_allowed_packet的值
    atguigu----kafka概述
    图像运算和图像增强十
    JAVA反射机制详解
    在项目中如何利用JS去修改CSS的属性值(二) --- :root+var()方法
    Java安全之深入了解SQL注入
    拼搏半个月,刷了 571道Java高频面试题喜提 offer
    WPF 项目开发入门(四) MVVM 模式 与 TreeView树组件
    景联文科技:关于语音标注,你知道多少?
    SQL书写顺序与执行顺序
  • 原文地址:https://blog.csdn.net/weixin_45591821/article/details/139462209