OpenCV cv::Mat之(一)创建数据对象

  上一篇:OpenCV图片色彩空间转换与图片保存 经常使用cv::Mat。在 OpenCV 中,cv::Mat 是一个非常重要的类,它负责存储图像以及其他多维数据。无论你是在进行简单的图像读取、图像变换,还是进行复杂的计算机视觉任务,对 cv::Mat 的深入理解都至关重要。本文将从多个角度介绍 cv::Mat 的基本概念、创建与初始化、数据访问、内存管理及常见应用实例,帮助你更好地使用 OpenCV 开发图像处理应用。

1、cv::Mat 的基本概念

cv::Mat 是 OpenCV 中用于表示矩阵数据的类,主要用于存储图像。一个 cv::Mat 对象由两部分组成:头部(header)和数据区(data)。

  • 头部:包含了图像的维度、通道数、数据类型、步长(step)等信息。

  • 数据区:存储了图像实际的像素数据。这个部分采用引用计数(reference counting)的方式管理内存,当多个 cv::Mat 对象共享同一数据时,只在所有对象都释放后才真正释放内存。这种设计使得,从而实现高效的内存管理。

    cv::Mat 在拷贝时(例如直接赋值=)只复制头部信息,而不复制实际数据。

    参考图来自其他网友,可以清楚了解基本结构:
    在这里插入图片描述
    在这里插入图片描述

2、cv::Mat 的创建与初始化

OpenCV 提供了多种方式来创建和初始化 cv::Mat 对象:

2.1 通过构造函数直接创建

你可以直接调用 cv::Mat 构造函数来创建一个指定大小和数据类型的矩阵。例如:运行后显示蓝色

#include <opencv2/opencv.hpp>
/**
 * 构造函数创建mat对象.
 * 
 */
int main() {
    // 创建一个 480x640,类型为 8 位 3 通道(彩色图像)的 cv::Mat 对象
    // Mat的排列是BGR
    cv::Mat image(480, 640, CV_8UC3);
    image = 255;
    cv::imshow("test", image);
    cv::waitKey();
    cv::destroyAllWindows();
    return 0;
}

cv::Mat image(480, 640, CV_8UC3)构造时:CV_8UC3数据类型宏格式说明:

数据深度(Data Depth)

  • CV_8U:8 位无符号整数,取值范围 0~255。常用于普通的图像像素表示。
  • CV_8S:8 位有符号整数,取值范围 -128~127,使用较少。
  • CV_16U:16 位无符号整数,取值范围 0~65535,常用于深度图或需要更大动态范围的图像。
  • CV_16S:16 位有符号整数。
  • CV_32S:32 位有符号整数。
  • CV_32F:32 位浮点数,常用于需要浮点精度的图像处理,比如滤波、梯度计算等。
  • CV_64F:64 位浮点数,用于更高精度的计算

通道数(Channel Count):C? 来表示,其中数字代表通道数:

  • C1:单通道图像,例如灰度图。
  • C3:三通道图像,通常表示彩色图像(BGR 顺序)。
  • C4:四通道图像,通常用于带有 Alpha 通道的图像(BGRA 顺序)

3. 常见组合举例

  • CV_8UC1:8 位无符号单通道图像,常用于灰度图。
  • CV_8UC3:8 位无符号三通道图像,常用于彩色图像(BGR 格式)。
  • CV_8UC4:8 位无符号四通道图像,适用于需要透明度通道的图像(如 PNG 中的 BGRA 格式)。
  • CV_16UC1:16 位无符号单通道图像,可能用于深度图或高动态范围图像。
  • CV_32FC1:32 位浮点单通道图像,经常出现在图像滤波、梯度计算等场景中。
  • CV_64FC1:64 位浮点单通道图像,适合对精度要求极高的计算。

2.2 使用预定义函数初始化

OpenCV 提供了常用的初始化函数,如 cv::Mat::zeroscv::Mat::ones 以及 cv::Mat::eye 来分别创建全零、全一或单位矩阵:

// 创建一个全零矩阵
cv::Mat zerosMat = cv::Mat::zeros(480, 640, CV_8UC3);

// 创建一个全一矩阵(所有像素值为 1)
cv::Mat onesMat = cv::Mat::ones(480, 640, CV_32F);

// 创建一个 5x5 的单位矩阵
cv::Mat eyeMat = cv::Mat::eye(5, 5, CV_64F);

2.3 读取图像文件

最常用的 cv::Mat 应用就是存储从文件中读取的图像数据:

	cv::Mat srcImage=cv::imread("E:/image/opencv-logo.png");
	// 判断图像是否读取成功
	if (srcImage.empty())
	{	
		std::cerr << "Error: Image not found." << std::endl;
		return -1;
	}
	imshow("srcImage", srcImage);
	cv::waitKey();
	cv::destroyWindow("srcImage");

2.4.深拷贝与浅拷贝

由于 cv::Mat 使用引用计数来管理数据内存,直接赋值操作不会复制实际数据,而只是共享同一块内存,这叫做浅拷贝
浅拷贝如果修改其中一个数据,同时也会影响另外一个

cv::Mat img1 = cv::imread("E:/image/opencv-logo.png");
cv::Mat img2 = img1;  // img2 与 img1 共享同一数据区域

如果你希望创建一个独立的拷贝(深拷贝),可以使用 clone()copyTo() 方法:

cv::Mat imgClone = img1.clone();
// 或者
cv::Mat imgCopy;
img1.copyTo(imgCopy);

这样 imgClone 和 imgCopy 都拥有独立的数据拷贝,对其中一个进行修改不会影响另一个。

3、参考代码

#include "stdio.h"
#include "opencv2/opencv.hpp"
#include <iostream>
using namespace cv;
int main()
{
	//构造创建mat对象-------------------------------------------------------------------------------------------
    cv::Mat image(480, 640, CV_8UC3);
    image = 255;
    cv::imshow("test", image);
    cv::waitKey();
    cv::destroyWindow("test");

	// 读取图像属于直接赋值-------------------------------------------------------------------------------------
	cv::Mat srcImage=cv::imread("E:/image/opencv-logo.png");
	// 判断图像是否读取成功
	if (srcImage.empty())
	{	
		std::cerr << "Error: Image not found." << std::endl;
		return -1;
	}
	imshow("srcImage", srcImage);
	cv::waitKey();
	cv::destroyWindow("srcImage");
	
	// 深拷贝-------------------------------------------------------------------------------------------
	cv::Mat image1;
	image1 = srcImage.clone();
	srcImage = Scalar(0, 0, 255);//赋值不影响image1;
	imshow("srcImage", srcImage);
	imshow("test", image1);
	cv::waitKey();
	cv::destroyAllWindows();
	// 浅拷贝-------------------------------------------------------------------------------------------
	srcImage = cv::imread("E:/image/opencv-logo.png");
	image1 = srcImage;
	srcImage = Scalar(0, 0, 255);//影响image数据
	imshow("srcImage", srcImage);
	imshow("test", image1);

	// 等待按键事件,按任意键关闭窗口
	cv::waitKey(0);
	destroyAllWindows();

	return 0;
}

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐