2.RV1126-OPENCV Mat理解和AT函数

news2025/6/5 1:11:03

一.Mat概念

        Mat 是整个图像存储的核心也是所有图像处理的最基础的类,Mat 主要存储图像的矩阵类型,包括向量、矩阵、灰度或者彩色图像等等。Mat由两部分组成:矩阵头,矩阵数据。矩阵头是存储图像的长度、宽度、色彩信息等头部信息;矩阵数据则是存储具体的图像数据。(我的理解就是,Mat是把图像分为一块一块矩阵类型保存,矩阵头显示这张图片基本信息,如这张图片多大,是不是彩色;具体的信息存储由矩阵数据存储)。

二.Mat通道

图中C1,C2,C3,C4代表几通道 ;前面CV_8U,8S,16U,16S,32U,32S代表用什么类型存储,例如:CV_8U就是用8位无符号类型存储,CV_8S就是用8位有符号存储。

  •  单通道(灰度图),就是图片是灰色的

  •  双通道(二值图像),就是黑白照片

  •  三通道(RGB 彩色图像)

  •  四通道(带 Alpha 的四通道图像),就是ARGB图像,更好看一点。

 三.Mat创建和构造方法

  • Mat(int rows, int cols, int type);

 重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是 rows、cols 以及存储类型 type
rows:行数,也指的是图像的高度,height。
cols:列数,也指的是图像的宽度,width。
type:通道类型,具体的看上面的图
示例:Mat t1 = Mat(300,300,CV_8UC1),这指的是创建一个 width:300,height:300,单通道的灰度图像.

  •  Mat(Size size, int type);

 重载的构造函数,这个构造函数在创建的时候,需要传入 Size 类和类型。
第一个传参:Size 结构体,Size(width,height)
第二个传参:type 通道类型,具体的看上面的图
示例:Mat t2 = Mat(Size(300,300),CV_8SC3),这指的是创建一个 width:300,height:300,三通道的灰度图像

  •  Mat(int rows, int cols, int type, const Scalar& s);

 重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是 rows、cols、存储类型 type、还有 Scalar 颜色标量。
第一个传参:rows 行数,也指的是图像的高度,height。
第二个传参:cols 列数,也指的是图像的宽度,width。
第三个传参:type 通道类型,具体的看上面的图
第四个传参:Scalar 颜色标量,Scalar(v0,v1,v2,v3),v0,v1,v2,v3 分别对应 OPENCV 颜色分量的四个值
示例: Mat mat = Mat(300,300,CV_8UC3,Scalar(255,255,255));表示的是创建cols:300,rows:300,三通道的灰度,颜色标量为白色的图像

  • Mat::zeros(rows,cols,type); 

 重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是 rows、cols 以及存储类型 type。ZEROS 相当于创建一张黑色的图片,每个像素通道为 0,并且 Scalar(0,0,0)。
第一个传参:rows 行数,也指的是图像的高度,height。
第二个传参:cols 列数,也指的是图像的宽度,width。
第三个传参:type 通道类型,具体的看上面的图
示例: Mat::zeros(300,300,CV_8SC3);,这指的是创建一个 width:300,height:300,三通道的彩色图像,Scalar(0,0,0),相当于Mat mat = Mat(300,300,CV_8SC3,Scalar(0,0,0));

  •  Mat::ones(rows,cols,type);

 重载的构造函数,这个构造函数在创建的时候,提供矩阵的大小,分别是 rows、cols 以及存储类型 type。ONES 相当于每个像素第一个通道为 1,后面两个通道为 0。
第一个传参:rows 行数,也指的是图像的高度,height。
第二个传参:cols 列数,也指的是图像的宽度,width。
第三个传参:type 通道类型,具体的看上面的图
示例: Mat::ones(300,300,CV_8SC3),这指的是创建一个 width:300,height:300, 三通道的彩色图像,Scalar(1,0,0),这等同于 Mat mat = Mat(300,300,CV_8SC3,Scalar(1,0,0));

四. imread读取图片信息和imwrite写入数据

  1. imread:读取图片信息。

 Mat imread( const String& filename, int flags = IMREAD_COLOR );

第一个参数:filename 图片的名称,名称可以是绝对路径也可以是相对路径
第二个参数:flags 标识符,flags 标识符默认为 IMREAD_COLOR。flags 一般分为三种:
IMREAD_UNCHANGED(<0)按原样加载图像(包括 alpha 通道(如果存在)
IMREAD_GRAYSCALE(0)将图像作为强度加载(灰白照片)
IMREAD_COLOR(> 0)以 RGB 格式加载图像(彩色照片)

返回值:Mat 矩阵

  • 例如:读取彩色三通道图片

Mat img_mat = imread("frame1.jpg");
printf("width = %d, height = %d, channels = %d\n", img_mat.cols, img_mat.rows, img_mat.channels());
...........................................................................................
输出结果:width = 1920, height = 1080, channels = 3

  • 例如:读取灰白单通道图片

Mat img_mat_gray = imread("gray_frame1.jpg", IMREAD_GRAYSCALE);
printf("img_mat_gray_width = %d, img_mat_gray_height = %d, img_mat_gray_channels = %d\n", img_mat_gray.cols,img_mat_gray.rows, img_mat_gray.channels());
.................................................................................................................
输出的结果:img_mat_gray_width = 1920, img_mat_gray_height = 1080, img_mat_gray_channels = 1 

2. imwrite:保存图片

 imwrite(const String& filename, InputArray image, const std::vector<int>& params);

第一个传参:filename 表示要保存的文件名
第二个传参:image 表示需要保存的图像数据
第三个传参:params 保存图像可选参数,主要是设置图像的质量,设置规则具体的我们来看看,该参数需要按照参数 id+参数值成对出现,可以出现多对参数值(比如 (paramId_1, paramValue_1, paramId_2, paramValue_2, ...)),但必须保证这些参数对是相关的,比如保存 JPG 图像时,只能使用和 JPEG 相关的参数 ID 进行组合使用。这里的 ID 基本上是 cv::ImwriteFlags。

  • 例如:使用默认的方式 imwrite 保存图片

Mat mat = Mat(300,300,CV_8UC3,Scalar(218,112,214));
imwrite("mat_demo.jpg", mat);
。。。。。。。。。。。。。。。。。。
上面是使用默认的方法保存图片,这种方法的所有参数都是默认选项。出来图片就是:

  •  使用 params 的方式 imwrite 保存图片

Mat quality_frame1_mat = imread("frame1.jpg");
std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 40};
imwrite("quality_mat_demo.jpg", quality_frame1_mat , params);
。。。。。。。。。。。。。。。。。。。。。。。。。
这种方法使用的是 params 参数的方式去设置,上面我们设置了图像的质量在 40,大家如果想设置其他功能可以参考上面的枚举进行设置。经过编码质量 40 的处理后的图像大小小于原图像大小,这说明编码质量关乎着文件的大小和画面的质量

五.代码具体

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace cv; //Must Need Write cv
using namespace std;

int main()
{
    //构造参数
    Mat t0 = Mat(300,300,CV_8UC1); //Create a 300x300 single channel matrix
    Mat t1 = Mat(Size(200,200),CV_8UC1); //Create a 300x300 single channel matrix
    Mat t2 = Mat(100,100,CV_8UC1,Scalar(255,255,255)); //Create a 300x300 single channel matrix
    Mat t3 = Mat::zeros(300,300,CV_8UC1); //Create a 300x300 single channel matrix
    Mat t4 = Mat::ones(200,200,CV_8UC1); //Create a 300x300 single channel matrix

    std::vector<int> params = {cv::IMWRITE_JPEG_QUALITY, 40};
    //imwrite写入数据
    imwrite("t0.jpg",t0);
    imwrite("t1.jpg",t1);
    imwrite("t2.jpg",t2);
    imwrite("t3.jpg",t3,params);
    imwrite("t4.jpg",t4);

    //imread读取数据
    Mat a0 = imread("t0.jpg");
    Mat a1 = imread("t3.jpg");
    Mat a2 = imread("t4.jpg",IMREAD_GRAYSCALE);

    printf("a0 heigh:%d weigh: %d channel:%d\n",a0.rows,a0.cols,a0.channels());
    printf("a3 heigh:%d weigh: %d channel:%d\n",a2.rows,a2.cols,a2.channels());
    return 0;
}

六.AT函数

1.作用         

        AT函数:就是用于修改Mat矩阵的像素值(上面用Mat创建的图片,这个图片都是一格一格像素点形成的,我们要想修改图片颜色,就要用到AT函数对像素点值修改就行)。AT 函数的修改一般需要循环 cols 和 rows 然后对每个像素点进行修改。

2. 定义

        at<typename>(int i, int j)

第一个参数:typename 指的是 OPENCV 的向量类型,(总结:1,2,3,4就是几通道,也可以理解为几维图像;后面b,s,w,i之类就是用什么类型读取,整型,还是字符读取),向量类型如下:

typedef Vec<uchar, 2> Vec2b:uchar 类型的数组,长度为 2, 它表示的是二维图像的位置信息、尺寸等等
typedef Vec<uchar, 3> Vec3b:uchar 类型的数组,长度为 3,它常用于彩色图像的像素值以及对 rgb 三个通道的处理,并且通道的像素值都是 uchar 类型
typedef Vec<uchar, 4> Vec4b:uchar 类型的数组,长度为 4,它常用于彩色图像的像素值以及对 argb 四个通道的处理,并且通道的像素值都是 uchar 类型
typedef Vec<short, 2> Vec2s:short 类型的数组,长度为 2, 它表示的是二维图像的位置信息、尺寸等等,但不能做像素处理
typedef Vec<short, 3> Vec3s:short 类型的数组,长度为 3, 它常用于彩色图像的像素值以及对 rgb 三个通道的处理,并且通道的像素值都是 short 类型
typedef Vec<short, 4> Vec4s:short 类型的数组,长度为 4, 它常用于彩色图像的像素值以及对 argb 四个通道的处理,并且通道的像素值都是 short 类型
typedef Vec<ushort, 2> Vec2w:ushort 类型的数组,长度为 2,它表示的是二维图像的位置信息、尺寸等等,但不能做像素处理
typedef Vec<ushort, 3> Vec3w:ushort 类型的数组,长度为 3,它常用于彩色图像的像素值以及对 rgb 三个通道的处理,并且通道的像素值都是 ushort 类型
typedef Vec<ushort, 4> Vec4w:ushort 类型的数组,长度为 4,它常用于彩色图像的像素值以及对 argb 四个通道的处理,并且通道的像素值都是 ushort 类型
typedef Vec<int, 2> Vec2i: int 类型的数组,长度为 2, 它表示的是一个包含 2 个整数的元素向量,并不能直接表示通道数
typedef Vec<int, 4> Vec4i: int 类型的数组,长度为 4, 它常用于彩色图像的像素值以及对 argb 四个通道的处理,并且通道的像素值都是 int 类型
typedef Vec<int, 6> Vec6i: int 类型的数组,长度为 6, 它常用于表示六维图像,包括:坐标、描述子、颜色直方等等,但是不能对六维图像直接进行处理
typedef Vec<int, 8> Vec8i: int 类型的数组,长度为 8, 它常用于表示八维图像,包括:坐标、描述子、颜色直方等等,但是不能对八维图像直接进行处理
typedef Vec<float, 2> Vec2f:float 类型的数组,长度为 2,它表示的是二维图像的位置信息,但不能做通道处理
typedef Vec<float, 3> Vec3f:float 类型的数组,长度为 3,它常用于彩色图像的像素值以及对 rgb 三个通道的处理,并且通道的像素值都是浮点数
typedef Vec<float, 4> Vec4f:float 类型的数组,长度为 4,它常用于彩色图像的像素值以及对 argb 四个通道的处理,并且通道的像素值都是浮点数
typedef Vec<float, 6> Vec6f: float 类型的数组,长度为 4,他用于处理 6 个维度的图像数据,需要注意的是 Vec6f 仅仅能表示具有 6 个维度的数据,并不可以对数据进行操作.
typedef Vec<double, 2> Vec2d:double 类型的数组,长度为 2,在图像处理中 Vec2d 仅仅只是表示具有 double 类型的图像数据,但是并不能直接操作数据像素
typedef Vec<double, 3> Vec3d:double 类型的数组,长度为 3,它常用于表示图像的彩色三通道,分别是 R(红色)、G(绿色)、B(蓝色),并且对于这三个通道的像素值进行 double 类型数据的处理
typedef Vec<double, 4> Vec4d:double 类型的数组,长度为 4,它常用于表示图像的彩色四通道,分别是 A(透明度)、R(红色)、G(绿色)、B(蓝色),并且对于这四个通道的像素值进行 double 类型数据的处理。
需要注意的是:一般 OPENCV 对像素的处理大部分都是用 uchar 类型,其他类型用的很少。 

第二个参数:i,指的是 rows,图像的行数据
第三个参数:j,指的是 cols,图像的列数据

3.代码示例

#include <opencv2/opencv.hpp>
#include <opencv2/dnn.hpp>
#include <opencv2/imgcodecs.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>

using namespace std;
using namespace cv;


int main()
{
    //修改三通道图片像素点值
    Mat img_mat = imread("frame1.jpg");//读取图片

    //用at函数遍历整个图片三通道像素点并修改像素点值
    for (int i = 0; i < img_mat.rows; i++)
    {
        for (int j = 0; j < img_mat.cols; j++)
        {

            img_mat.at<Vec3b>(i, j)[0] = img_mat.at<Vec3b>(i, j)[0] - 10;
            img_mat.at<Vec3b>(i, j)[1] -= 50;
            img_mat.at<Vec3b>(i, j)[2] -= 10;
        }        
    }
    //保存修改后的图片
    imwrite("frame2.jpg", img_mat);


    //修改单通道图片像素点值
    Mat grayImage;
    Mat before_Image;
    cvtColor(img_mat, before_Image, COLOR_RGB2GRAY);
    cvtColor(img_mat, grayImage, COLOR_RGB2GRAY);

    //用at函数遍历整个图片单通道像素点并修改像素点值
    for (int i = 0; i < grayImage.rows; i++)
    {
        for (int j = 0; j < grayImage.cols; j++)
        {
            grayImage.at<uchar>(i, j) = 50 - grayImage.at<uchar>(i, j);
        }
    }

    //保存修改后的图片
    imwrite("frame3.jpg", before_Image);
    imwrite("frame4.jpg", grayImage);

    return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2397063.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

unidbg patch 初探 微博deviceId 案例

声明 本文章中所有内容仅供学习交流使用&#xff0c;不用于其他任何目的&#xff0c;抓包内容、敏感网址、数据接口等均已做脱敏处理&#xff0c;严禁用于商业用途和非法用途&#xff0c;否则由此产生的一切后果均与作者无关&#xff01; 逆向过程 看了b站迷人瑞信那个由于是…

循序渐进 Android Binder(一):IPC 基本概念和 AIDL 跨进程通信的简单实例

Binder 给人的第一印象是”捆绑者“&#xff0c;即将两个需要建立关系的事物用某些工具束缚在一起。在 Android 中&#xff0c;Binder 是一种高效的跨进程通信&#xff08;IPC&#xff09;机制&#xff0c;它将可以将运行在不同进程中的组件进行绑定&#xff0c;以实现彼此通信…

网络安全之Web渗透加解密

项目基本使用 准备环境&#xff1a;node.js python chrome npm install chrome-remote-interface pip install playwright playwright install chromium pip install mitmproxy ............... 第一步启动cdp.js。 第二步使用python .\cdp_load.py vue_demo&#xff0c;连…

【LeetCode 题解】两数之和(C++/Python 双解法):从语法到算法的全面解析

【LeetCode题解】两数之和&#xff08;C/Python双解法&#xff09;&#xff1a;从语法到算法的全面解析 一、题目描述 题目链接&#xff1a;1. 两数之和 难度&#xff1a;简单 要求&#xff1a;给定一个整数数组 nums 和一个整数目标值 target&#xff0c;在数组中找出两个数…

【机器学习基础】机器学习入门核心算法:集成学习(Ensemble Learning)

机器学习入门核心算法&#xff1a;集成学习&#xff08;Ensemble Learning&#xff09; 1. 算法逻辑核心逻辑&#xff1a; 2. 算法原理与数学推导2.1 Bagging&#xff08;Bootstrap Aggregating&#xff09;2.2 Boosting2.3 Stacking 3. 模型评估评估指标基学习器选择策略 4. 应…

【TMS570LC4357】之相关驱动开发学习记录1

系列文章目录 【TMS570LC4357】之工程创建 【TMS570LC4357】之工程配置修改 【TMS570LC4357】之HALCOGEN使用 【TMS570LC4357】之相关问题及解决 ——————————————————— 前言 记录笔者在第一次使用TMS570过程中对外设驱动的一些学习碎片。 1. RTI 1.1 添…

RAG入门 - Retriever(1)

文章目录 环境准备知识库加载1. Retriever - embeddings &#x1f5c2;️1.1 将文档拆分为chunks1.2 词嵌入1.3 构建向量数据库Nearest Neighbor search algorithm &#xff08;最近邻搜索算法&#xff09;Distances &#xff08;距离&#xff09;点积&#xff08;Dot Product&…

pyspark实践

1。pyspark是什么 PySpark 是 Apache Spark 的官方 Python 接口&#xff0c;它使得 Python 开发者能够访问 Spark 的核心功能&#xff0c;如&#xff1a; Spark SQL&#xff1a;用于执行 SQL 查询以及读取数据的库&#xff0c;支持多种数据格式和存储系统。py.qizhen.xyz Data…

【深度学习新浪潮】多模态模型如何处理任意分辨率输入?

多模态模型处理任意分辨率输入的能力主要依赖于架构设计的灵活性和预处理技术的结合。以下是核心方法及技术细节: 一、图像模态的分辨率处理 1. 基于Transformer的可变补丁划分(ViT架构) 补丁化(Patch Embedding): 将图像分割为固定大小的补丁(如1616或3232像素),不…

K-匿名模型

K-匿名模型是隐私保护领域的一项基础技术&#xff0c;防止通过链接攻击从公开数据中重新识别特定个体。其核心思想是让每个个体在发布的数据中“隐匿于人群”&#xff0c;确保任意一条记录至少与其他K-1条记录在准标识符&#xff08;Quasi-Identifiers, QIDs&#xff09;上不可…

UE5蓝图暴露变量,在游戏运行时修改变量实时变化、看向目标跟随目标Find Look at Rotation、修改玩家自身弹簧臂

UE5蓝图中暴露变量&#xff0c;类似Unity中public一个变量&#xff0c;在游戏运行时修改变量实时变化 1&#xff0c;添加变量 2&#xff0c;设置变量的值 3&#xff0c;点开小眼睛&#xff0c;此变量显示在编辑器中&#xff0c;可以运行时修改 看向目标跟随目标Find Look at R…

Python-matplotlib中的Pyplot API和面向对象 API

matplotlib中的Pyplot API和面向对象 API Pyplot API&#xff08;状态机模式&#xff09;面向对象 API 详解二者差别核心区别方法命名差异注意事项差别举例 &#x1f345; Pyplot API&#xff08;状态机模式&#xff09;和面向对象 API 是两种不同的编程接口.&#x1f345; 它们…

FastAPI安全认证:从密码到令牌的魔法之旅

title: FastAPI安全认证:从密码到令牌的魔法之旅 date: 2025/06/02 13:24:43 updated: 2025/06/02 13:24:43 author: cmdragon excerpt: 在FastAPI中实现OAuth2密码流程的认证机制。通过创建令牌端点,用户可以使用用户名和密码获取JWT访问令牌。代码示例展示了如何使用Cry…

java对接bacnet ip协议(跨网段方式)

1、环境准备 #maven环境<repositories><repository><id>ias-releases</id><url>https://maven.mangoautomation.net/repository/ias-release/</url></repository></repositories><dependencies><dependency><…

LabVIEW超宽带紧凑场测量系统

采用 LabVIEW 开发超宽带紧凑场测量系统&#xff0c;实现天线方向图、目标雷达散射截面&#xff08;RCS&#xff09;及天线增益的自动化测量。通过品牌硬件设备&#xff0c;优化系统架构&#xff0c;解决传统测量系统在兼容性、数据处理效率及操作便捷性等方面的问题&#xff0…

编译rustdesk,使用flutter、hwcodec硬件编解码、支持Windows 7系统

目录 安装相应的环境安装visual studio安装vpkg安装rust开发环境安装llvm和clang编译源码下载源码使用Sciter作为UI的(已弃用)使用flutter作为UI的(主流)下载flutter sdk桥接静默安装支持Windows 7系统最近某desk免费的限制越来越多,实在没办法,平时远程控制用的比较多,…

ROS机器人和NPU的往事和新知-250602

往事&#xff1a; 回顾一篇五年前的博客&#xff1a; ROS2机器人笔记20-12-04_ros2 移植到vxworks-CSDN博客 里面提及专用的机器人处理器&#xff0c;那时候只有那么1-2款专用机器人处理器。 无关&#xff1a; 01&#xff1a; 每代人的智商和注意力差异是如何出现的-250602-…

【从零开始学习QT】信号和槽

目录 一、信号和槽概述 信号的本质 槽的本质 二、信号和槽的使用 2.1 连接信号和槽 2.2 查看内置信号和槽 2.3 通过 Qt Creator 生成信号槽代码 自定义槽函数 自定义信号 自定义信号和槽 2.4 带参数的信号和槽 三、信号与槽的连接方式 3.1 一对一 &#xff08;1&…

MCP调研

什么是 MCP MCP&#xff08;Model Context Protocol&#xff0c;模型上下文协议&#xff09;&#xff0c;是由 Anthropic 在 2024 年 11 月底推出的开放标准协议&#xff0c;旨在统一大型语言模型&#xff08;LLM&#xff09;与外部数据源、工具的通信方式。MCP 的主要目的在于…

TDengine 运维——巡检工具(定期检查)

背景 TDengine 在运行一段时间后需要针对运行环境和 TDengine 本身的运行状态进行定期巡检&#xff0c;本文档旨在说明如何使用巡检工具对 TDengine 的运行环境进行自动化检查。 安装工具使用方法 工具支持通过 help 参数查看支持的语法 Usage: taosinspect [OPTIONS]Check…