昊虹AI笔记网

 找回密码
 立即注册
搜索
查看: 1110|回复: 0
收起左侧

OpenCV_Mat类对象的基本操作、常用操作及相关成员函数介绍

[复制链接]

239

主题

241

帖子

931

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
931
昊虹君 发表于 2022-10-16 13:15 | 显示全部楼层 |阅读模式
OpenCV_Mat类对象的基本操作、常用操作及相关成员函数介绍

OpenCV的Mat类有许多成员函数,我们可以利用这些成员函数实现Mat类对象的基本操作、常用操作。

本文列举出Mat类常用的成员函数及其功能。

目录
  • 01-成员函数Mat::row():获取矩阵的某行(与原矩阵共用内存空间)
        01-1 成员函数Mat::row()的简单示例代码
        01-2 成员函数Mat::row()的应用:实现矩阵的行间运算
  • 02-成员函数Mat::col():获取矩阵的某列(与原矩阵共用内存空间)
  • 03-成员函数Mat::rowRange():获取矩阵的某几行(与原矩阵共用内存空间)
  • 04-成员函数Mat::colRange():获取矩阵的某几列(与原矩阵共用内存空间)
  • 05-成员函数Mat::clone():创建矩阵或矩阵子矩阵的副本(深拷贝,不与原矩阵共用内存空间)
  • 06-成员函数Mat::copyTo():复制矩阵到另一矩阵(深拷贝,不与原矩阵共用内存空间)
  • 07-成员函数Mat::convertTo():实现矩阵元素的数据类型的转换
  • 08-成员函数Mat::zeros():初始化一个所有元素值都为零的矩阵
  • 09-成员函数Mat::ones():初始化一个所有元素值都为1的矩阵
  • 10-成员函数Mat::size():获取矩阵的size(列数、行数)
  • 11-成员函数Mat:type():)获取矩阵的type
  • 12-成员函数Mat:channels():获取矩阵的通道数
  • 13-成员函数Mat:at():访问某个矩阵元素的值
  • 14-成员函数Mat::depth():获取矩阵元素的数据类型
  • 15-成员函数Mat::operator()(const Rect& roi) const:选择ROI区域(感兴趣矩形区域),并实现深拷贝和浅拷贝
        15-1 深拷贝ROI区域
        15-2 浅拷贝ROI区域
  • 15-3 将一个矩阵(图像)复制到另一矩阵(图像)的指定区域(ROI)【深拷贝】
  • 16-成员函数Mat:empty():判断Mat对象的数据是否为空


01-成员函数Mat::row():获取矩阵的某行(与原矩阵共用内存空间)
成员函数Mat::row()用于获取矩阵的某行(与原矩阵共用内存空间)

01-1 成员函数Mat::row()的简单示例代码
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

int main( )
{
	cv::Mat Image1( 3,4, CV_8UC1, cv::Scalar(0) );

	uchar value = 1;
	for (int i = 0; i < Image1.rows; i++)
	{
		for (int j = 0; j < Image1.cols; j++)
		{
		    Image1.at<uchar>(i, j) = value;
			value++;
		}
	}

	std::cout <<"Image1的数据如下:\n"<<Image1 << std::endl<< std::endl;

	std::cout <<"Image1的第0行的数据如下:\n"<<Image1.row(0) << std::endl<< std::endl;

	cv::Mat Image2 = Image1.row(0);

	std::cout <<"Image2的数据如下:\n"<<Image2 << std::endl<< std::endl;

	Image1.at<uchar>(0, 0) = 100;

	std::cout <<"修改Image1相应位置的数据后再看Image2的数据:\n"<<Image2 << std::endl<< std::endl;


	return 0;
}


运行结果如下:


01-2 成员函数Mat::row()的应用:实现矩阵的行间运算

示例代码如下:
[C++] 纯文本查看 复制代码
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
int main( )
{
	cv::Mat Image1( 3,4, CV_8UC1, cv::Scalar(0) );

	uchar value = 1;
	for (int i = 0; i < Image1.rows; i++)
	{
		for (int j = 0; j < Image1.cols; j++)
		{
		    Image1.at<uchar>(i, j) = value;
			value++;
		}
	}

	std::cout <<"原Image1的数据如下:\n"<<Image1 << std::endl<< std::endl;

	//Image1的第0行元素变换成Image1的第2行元素乘以2
	Image1.row(0) = Image1.row(2) * 2;

	std::cout <<"进行行间运算后Image1的数据如下:\n"<<Image1 << std::endl<< std::endl;

	return 0;
}


运行结果如下:


02-成员函数Mat::col():获取矩阵的某列(与原矩阵共用内存空间)
成员函数Mat::col()用于获取矩阵的某列(与原矩阵共用内存空间)

示例代码就不给了,因为这个的使用与上一个成员函数Mat::row()的使用一模一样,只是Mat::col()获取到的是列,而Mat::row()获取到的是行。


03-成员函数Mat::rowRange():获取矩阵的某几行(与原矩阵共用内存空间)
成员函数Mat::rowRange()用于获取矩阵的某几行(与原矩阵共用内存空间)

成员函数Mat::rowRange()的原型如下:
  1. Mat cv::Mat::rowRange(int startrow, int endrow) const
复制代码

参数startrow和参数endrow设置要选取的连续行区域的起始行和结束行。注意由这两个参数设置选取的行区间[startrow, endrow)是左开右闭区间。举个例子,[0, 2)选取的是第0行和第1行,没有第二行。

示例代码如下:
  1. Image1.rowRange(1,4) = 88; //把第1行到第三行的元素的值修改为88
  2. std::cout << Image1.rowRange(1,4) << std::endl; //输 Image1第一行至第三行的数据
复制代码


04-成员函数Mat::colRange():获取矩阵的某几列(与原矩阵共用内存空间)
成员函数Mat::colRange()用于获取矩阵的某几列(与原矩阵共用内存空间)
该成员函数与上一个成员函数Mat::rowRange()的使用方法完全一样,这里就不再赘述。


05-成员函数Mat::clone():创建矩阵或矩阵子矩阵的副本(深拷贝,不与原矩阵共用内存空间)
成员函数Mat::clone()用于创建矩阵或矩阵子矩阵的副本(深拷贝,不与原矩阵共用内存空间)

示例代码如下:
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

int main( )
{
	cv::Mat Image1( 3,4, CV_8UC1, cv::Scalar(0) );

	uchar value = 1;
	for (int i = 0; i < Image1.rows; i++)
	{
		for (int j = 0; j < Image1.cols; j++)
		{
		    Image1.at<uchar>(i, j) = value;
			value++;
		}
	}

	cv::Mat Image2( 2, 2, CV_8UC1, cv::Scalar(5) );
	cv::Mat Image3;

	Image2 = Image1.rowRange(0,2).clone();
	Image3 = Image1.clone();

	std::cout <<"Image1的数据如下:\n"<<Image1 << std::endl<< std::endl;
	std::cout <<"Image2的数据如下:\n"<<Image2<< std::endl<< std::endl;
	std::cout <<"Image3的数据如下:\n"<<Image3<< std::endl<< std::endl;

	return 0;
}


运行结果如下:



06-成员函数Mat::copyTo():复制矩阵到另一矩阵(深拷贝,不与原矩阵共用内存空间)
成员函数Mat::copyTo()用于复制矩阵到另一矩阵(深拷贝,不与原矩阵共用内存空间)

示例代码如下:
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

int main( )
{
	cv::Mat Image1( 3,4, CV_8UC1, cv::Scalar(0) );

	uchar value = 1;
	for (int i = 0; i < Image1.rows; i++)
	{
		for (int j = 0; j < Image1.cols; j++)
		{
		    Image1.at<uchar>(i, j) = value;
			value++;
		}
	}

	cv::Mat Image2( 2, 2, CV_8UC1, cv::Scalar(5) );
	cv::Mat Image3;

	Image1.rowRange(0,2).copyTo(Image2);
	Image1.copyTo(Image3);

	std::cout <<"Image1的数据如下:\n"<<Image1 << std::endl<< std::endl;
	std::cout <<"Image2的数据如下:\n"<<Image2<< std::endl<< std::endl;
	std::cout <<"Image3的数据如下:\n"<<Image3<< std::endl<< std::endl;


	return 0;
}



运行结果如下:

从上面的运行结果我们可以看出函数clone()和函数copyTo()在使用上及效果上几乎是一样的,事实上,这两个函数在使用和效果上几乎也是没有差别的,并且它们都不与原矩阵共用内存空间。
但是它们俩还是有细微的差别,它们俩的细微差别详见链接 https://www.hhai.cc/thread-76-1-1.html


07-成员函数Mat::convertTo():实现矩阵元素的数据类型的转换
成员函数Mat::convertTo()用于实现矩阵元素的数据类型的转换

示例代码如下:
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>

#include <iostream>
int main( )
{
	cv::Mat image1( 2, 2, CV_8UC1,cv::Scalar(9));
	std::cout <<"原imag1的数据类型为:"<<image1.depth()<< std::endl<< std::endl;
	image1.convertTo(image1, CV_16UC1);
	std::cout <<"经转换后的image1的数据类型为:"<<image1.depth() << std::endl<< std::endl;

  return 0;
}



运行结果如下:

从运行结果可以看出,矩阵元素的数据类型被转换了。
另外,还要提示一下,使用convertTo()还能实现原矩阵通过经典线性变换到一个新的矩阵哦。


08-成员函数Mat::zeros():初始化一个所有元素值都为零的矩阵
可利用Mat类的成员函数Mat::zeros()实现初始化一个所有元素值都为零的矩阵,详细介绍请参看链接 https://www.hhai.cc/thread-71-1-1.html

09-成员函数Mat::ones():初始化一个所有元素值都为1的矩阵
可利用Mat类的成员函数Mat::ones()实现初始化一个所有元素值都为1的矩阵,成员函数Mat::ones()的使用与上一个Mat::zeros()的使用完全相同,这里就不再详细介绍了。

10-成员函数Mat::size():获取矩阵的size(列数、行数)
可利用Mat类的成员函数Mat::size()获取矩阵的size(列数、行数),详细介绍请参看链接 https://www.hhai.cc/thread-78-1-1.html

11-成员函数Mat:type():)获取矩阵的type
可利用Mat类的成员函数Mat:type()获取矩阵的type,详细介绍请参看链接 https://www.hhai.cc/thread-78-1-1.html

12-成员函数Mat:channels():获取矩阵的通道数
可利用Mat类的成员函数Mat:channels()获取矩阵的通道数,详细介绍请参看链接 https://www.hhai.cc/thread-78-1-1.html

13-成员函数Mat:at():访问某个矩阵元素的值
可利用Mat类的成员函数Mat:at()访问某个矩阵元素的值。
格式为M.at<typename>(i,j)
示例:
image.at<Vec3b>(i,j):取出灰度图像image中第i行第j列点的像素值;
image.at<Vec3b>(i,j)[k]:取出彩色图像image第k通道中第i行第j列点的像素值。
如何想了解“Vec3b”为何物,可以参考链接 https://www.hhai.cc/thread-80-1-1.html
注意:函数at()的第一个参数代表行索引,第二个参数代表列索引。
代码例子:
[C++] 纯文本查看 复制代码
//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术

//博主微信/QQ 2487872782
//QQ群 271891601
//欢迎技术交流与咨询

//OpenCV版本 OpenCV3.0

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
	//图像为单通道的情况
	Mat A1 = Mat::zeros(2, 3, CV_8UC1);

	//注意:第一个参数代表行索引,第二个参数代表列索引
	A1.at<uchar>(1, 2) = 55;

	cout << "A1中的数据为:" << endl;
	cout << A1 << endl << endl;


	//图像为三通道的情况
	Mat B1 = Mat::zeros(2, 3, CV_8UC3);

	B1.at<Vec3b>(1, 2)[0] = 66;
	B1.at<Vec3b>(1, 2)[1] = 77;
	B1.at<Vec3b>(1, 2)[2] = 88;

	cout << "B1中的数据为:" << endl;
	cout << B1 << endl << endl;


	return(0);
}

运行结果如下:


14-成员函数Mat::depth():获取矩阵元素的数据类型
可利用Mat类的成员函数Mat::depth()获取矩阵元素的数据类型,详细介绍请参看链接 https://www.hhai.cc/thread-78-1-1.html

15-成员函数Mat::operator()(const Rect& roi) const:选择ROI区域(感兴趣矩形区域),并实现深拷贝和浅拷贝
可利用Mat类的成员函数Mat::operator()(const Rect& roi) const选择ROI区域(感兴趣矩形区域)。
operator()表示Mat类对运算符()的重载,关于运算符重载,可以参见博文 https://www.hhai.cc/thread-81-1-1.html
关于const的含义,可以参见博文 https://www.hhai.cc/thread-82-1-1.html

15-1 深拷贝ROI区域
深拷贝ROI区域示例代码:
[C++] 纯文本查看 复制代码
//利用Rect选择区域(100, 180, 150, 50)
int xRoi = 80;
int yRoi = 180;
int widthRoi = 150;
int heightRoi = 100;
srcImage(cv::Rect(xRoi,yRoi,widthRoi,heightRoi)).copyTo(roiImage);

上面的代码实现了把srcImage中的区域(100, 180, 150, 50)深拷贝到给了roiImage。
ROI区域:cv::Rect(xRoi,yRoi,widthRoi,heightRoi)代表下面这个矩形:
矩形区域左上角顶点的坐标为(100, 180)
矩形区域在x方向上的长度为150;
矩形区域在y方向上长度为180;

15-2 浅拷贝ROI区域
浅拷贝ROI区域示例代码:
[C++] 纯文本查看 复制代码
#include <opencv2/opencv.hpp>

#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	cv::Mat A1(7, 7, CV_8UC1, cv::Scalar(0));
	cout << "A1的数据为:\n" << A1 << endl << endl;

	int xRoi = 1;
	int yRoi = 1;
	int widthRoi = 3;
	int heightRoi = 4;

	Mat A1_roi = A1(cv::Rect(xRoi, yRoi, widthRoi, heightRoi));
	cout << "A1_roi的数据为:\n" << A1_roi << endl << endl;

	A1_roi.at<uchar>(1, 1) = 1;
	cout << "对A1_roi进行修改后A1_roi的数据为:\n" << A1_roi << endl << endl;
	cout << "对A1_roi进行修改后A1的数据为:\n" << A1 << endl << endl;

	return(0);
}

运行结果如下:

从上面的运行结果来看,对浅拷贝对象A1_roi的修改也会影响到A1中相应元素的值。

15-3 将一个矩阵(图像)复制到另一矩阵(图像)的指定区域(ROI)【深拷贝】
示例代码:

[C++] 纯文本查看 复制代码
#include <opencv2/opencv.hpp>

#include <iostream>

using namespace cv;
using namespace std;

int main()
{
	cv::Mat A1(7, 7, CV_8UC1, cv::Scalar(0));
	cv::Mat B1(3, 3, CV_8UC1, cv::Scalar(1));

	int xRoi = 1;
	int yRoi = 1;
	int widthRoi = 3;
	int heightRoi = 3;

	cv::Rect A1_roi = cv::Rect(xRoi, yRoi, widthRoi, heightRoi);

	B1.copyTo(A1(A1_roi)); //这是关键代码,将B1的数据复制到了A1中的指定区域

	B1.at<uchar>(1, 1) = 5; //这是为了测试看是不是深拷贝

	cout << "A1的数据为:\n" << A1 << endl << endl;

	return(0);
}


以上代码将B1的数据复制到了A1中的指定区域。
运行结果如下:



16-成员函数Mat:empty():判断Mat对象的数据是否为空
对于成员函数Mat:empty(),如果Mat对象没有数据元素,则返回ture。
我们通常利用它检测图像的读取是否成功。
在图像读取完成后,我们可以利用下面的语句判断是否读取成功:
[C++] 纯文本查看 复制代码
	if (src_image.empty())
	{
		std::cout << "Error: Could not load image" << std::endl;
		return 0;
	}

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|昊虹AI笔记网 ( 蜀ICP备2024076726 )

GMT+8, 2024-5-17 06:27 , Processed in 0.027388 second(s), 23 queries .

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表