OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累

如题,问题很简单,也很基础,但是却是高频使用的,有时候,莫名地就忘了格式,或者忘了还有这个操作,所以有必要写一篇博文把OpenCV的Mat类对象的初始化、再初始化、属性获取、基本操作”的示例代码进行个积累汇总,以便自己Coding时取用。

目录

  • 1 Mat类对象的6种初始化方法
    • 1-附1 初始化矩阵的每一个元素为不同的任意值(利用重载运算符<<)
    • 1-附2-通过别的矩阵的属性值创建一个新的矩阵
  • 2 利用成员函数creat()重新调整矩阵的属性
  • 3 利用相关成员函数获取矩阵的属性
    • 3-1 利用成员函数depth()获取矩阵元素的数据类型
    • 3-2 利用成员函数channels()获取矩阵的通道数
    • 3-3 利用成员函数type()获取矩阵的数据类型和通道数
  • 4 利用成员函数convertTo()实现数据类型的转换
  • 5 与尺寸有关的操作
    • 5-1 获取矩阵的行数或列数
    • 5-2 获取矩阵的尺寸(size)
    • 5-3 通过函数size()获取另一矩阵的尺寸来新建一个矩阵
  • 5与6之间插一个:利用成员函数at()访问具体的像素值
  • 6 通过成员函数row()获取矩阵的某行(与原矩阵共用内存空间)
  • 7 通过成员函数col()获取矩阵的某列(与原矩阵共用内存空间)
  • 8-1 通过成员函数rowRange()获取矩阵的某几行(与原矩阵共用内存空间)
  • 8-2 通过成员函数colRange()获取矩阵的某几列(与原矩阵共用内存空间)
  • 9 利用Mat::operator()(const Rect& roi) const 选择感兴趣矩形区域ROI(深拷贝ROI和浅拷贝ROI)
    • 9-附1 将一个矩阵(图像)复制到另一矩阵(图像)的指定区域(ROI)【深拷贝】
  • 10 矩阵内部的行运算
  • 11 矩阵内部的列运算
  • 12 利用函数clone()创建矩阵或矩阵子矩阵的副本(深拷贝,不与原矩阵共用内存空间)
  • 13 利用函数copyTo()复制矩阵到另一矩阵(深拷贝,不与原矩阵共用内存空间)
  • 14 利用MAT类成员函数at()访问矩阵元素的数据值

1 Mat类对象的6种初始化方法

详情见下面的截图:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第1张图片
第01-第06示例代码如下:

//出处:昊虹AI笔记网(hhai.cc)
//用心记录计算机视觉和AI技术
 
//OpenCV版本 OpenCV3.0

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
  // 方法1:创建无初始化矩阵
  cv::Mat image1; 

  // 方法2:创建大小为2x3,数据类型为8位无符号整数的单通道矩阵
  cv::Mat image2( 2, 3, CV_8UC1 );

  // 方法3:创建大小为3x2,数据类型为8位无符号整数的三通道矩阵
  cv::Mat image3( cv::Size(2,3), CV_8UC1 );

  // 方法4:创建大小为2x3,数据类型为32位浮点型的两通道矩阵,两个通道的数据初始值分别为1和2
  cv::Mat image4( 2, 3, CV_32FC2, cv::Scalar(1,2) );

  // 方法5:创建大小为3x2,数据类型为8位无符号的三通道矩阵,三个通道的数据初始值分别为1、2、3
  cv::Mat image5( cv::Size(2,3), CV_8UC3, cv::Scalar(1,2,3) );

  //方法6:创建Mat对象image6,由于是引用传递,所以image6和image2共用内存空间。
  cv::Mat image6( image2 );

  // 输出矩阵结果
  std::cout <<"imag1的数据如下:\n"<<image1 << std::endl<< std::endl;
  std::cout <<"imag2的数据如下:\n"<<image2 << std::endl<< std::endl;
  std::cout <<"imag3的数据如下:\n"<<image3 << std::endl<< std::endl;
  std::cout <<"imag4的数据如下:\n"<<image4 << std::endl<< std::endl;
  std::cout <<"imag5的数据如下:\n"<<image5 << std::endl<< std::endl;
  std::cout <<"imag6的数据如下:\n"<<image6 << std::endl<< std::endl;
  return 0;
}

运行结果如下图所示:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第2张图片
从上面的运行结果我们可以看出,MAT对象的数据如果没有指定初始值,那么其值为205,注意不是255
要特别注意的地方是:使用cv::Size()设定大小时,第一个参数是指矩阵有多少列,第二个参数是指矩阵有多少行,即cv::Size(width,height),比如上面代码中的方法3和方法5

1-附1 初始化矩阵的每一个元素为不同的任意值(利用重载运算符<<)

示例代码如下:

#include 
#include 

using namespace std;

int main()
{

	cv::Mat A1 = (cv::Mat_<uchar>(3, 3) <<	1, 2, 3,
											4, 5, 6,
											7, 8, 9);


	cv::Mat B1 = (cv::Mat_<float>(3, 3) <<	0.1, 0.2, 0.3,
											0.4, 0.5, 0.6,
											0.7, 0.8, 0.9);

	cv::Mat C1 = (cv::Mat_<double>(3, 3) << 0.1, 0.2, 0.3,
											0.4, 0.5, 0.6,
											0.7, 0.8, 0.9);

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


	return(0);
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第3张图片
注意B1和C1输出的不同,所以当数据为浮点型时能用double型就用double型。

1-附2-通过别的矩阵的属性值创建一个新的矩阵

示例代码如下:

//OpenCV版本:3.0.0
//VS版本:2013

#include 

#include 
using namespace std;

int main()
{

	cv::Mat A1 = (cv::Mat_<float>(2, 3) << 1, 200, 3, 4, 5, 6);
	cout << "A1中的数据为:\n" << A1 << endl << endl;

	cv::Mat B1(A1.size(), A1.type(), cv::Scalar(1));
	cout << "B1中的数据为:\n" << B1 << endl << endl;



	return(0);
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第4张图片

2 利用成员函数creat()重新调整矩阵的属性

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
	 cv::Mat image1( 2, 2, CV_8UC1,cv::Scalar(9));
	 std::cout <<"原imag1的数据如下:\n"<<image1 << std::endl<< std::endl;

	 image1.create(3, 3, CV_32FC2); //注意,函数create()不允许设置调整后矩阵元素的值
	// 输出矩阵结果
	std::cout <<"经调整后imag1的数据如下:\n"<<image1 << std::endl<< std::endl;

  return 0;
}

运行结果如下图所示:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第5张图片
这里要特别注意:函数create()不允许设置调整后矩阵元素的值,这也是为什么它不经常被大家使用的原因。
函数create()的常用原型如下:

void cv::Mat::create(	int 	rows,
						int 	cols,
						int 	type 
					)	

可见,确实是没有设置调整后矩阵元素的值的参数。

3 利用相关成员函数获取矩阵的属性

3-1 利用成员函数depth()获取矩阵元素的数据类型

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
	 cv::Mat image1( 2, 2, CV_8UC1,cv::Scalar(9));
	 cv::Mat image2( 2, 2, CV_8SC1,cv::Scalar(9));
	 cv::Mat image3( 2, 2, CV_16UC1,cv::Scalar(9));
	 cv::Mat image4( 2, 2, CV_16SC1,cv::Scalar(9));
	 cv::Mat image5( 2, 2, CV_32SC1,cv::Scalar(9));
	 cv::Mat image6( 2, 2, CV_32FC1,cv::Scalar(9));
	 cv::Mat image7( 2, 2, CV_64FC1,cv::Scalar(9));

 	 std::cout <<"image1 depth:" <<image1.depth() << std::endl<< std::endl;
	 std::cout <<"image2 depth:" <<image2.depth() << std::endl<< std::endl;
	 std::cout <<"image3 depth:" <<image3.depth() << std::endl<< std::endl;
	 std::cout <<"image4 depth:" <<image4.depth() << std::endl<< std::endl;
	 std::cout <<"image5 depth:" <<image5.depth() << std::endl<< std::endl;
	 std::cout <<"image6 depth:" <<image6.depth() << std::endl<< std::endl;
	 std::cout <<"image7 depth:" <<image7.depth() << std::endl<< std::endl;
	 
	return 0;
}

运行结果如下图所示:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第6张图片
从代码和运行结果我们可以得出下面的对应关系:

0代表CV_8U - 8-bit unsigned integers ( 0..255 )
1代表CV_8S - 8-bit signed integers ( -128..127 )
2代表CV_16U - 16-bit unsigned integers ( 0..65535 )
3代表CV_16S - 16-bit signed integers ( -32768..32767 )
4代表CV_32S - 32-bit signed integers ( -2147483648..2147483647 )
5代表CV_32F - 32-bit floating-point numbers ( -FLT_MAX..FLT_MAX, INF, NAN )
6代表CV_64F - 64-bit floating-point numbers ( -DBL_MAX..DBL_MAX, INF, NAN )

3-2 利用成员函数channels()获取矩阵的通道数

这个成员函数的使用和上一个示例一样,只是把上一个示例中的depth()换成channels()。示例代码如下:

std::cout <<"Image2 channels:" << Image2.channels() << std::endl;

3-3 利用成员函数type()获取矩阵的数据类型和通道数

示例代码如下:

#include 
#include 
#include
#include 

#include 

using namespace cv;
 
int main()
{
	//源图像  
	Mat img_input = imread("F:/material/images/P0005-BaoXiaofeng.jpg");

	Mat img_output(img_input.size(), img_input.type());

	std::cout<<"img_input channels:" << img_input.channels() << std::endl<< std::endl;

	std::cout<<"img_input depth:" << img_input.depth() << std::endl<< std::endl;

	std::cout<<"img_input type:" << img_input.type() << std::endl<< std::endl;

	std::cout<<"img_output channels:" << img_output.channels() << std::endl<< std::endl;

	std::cout<<"img_output depth:" << img_output.depth() << std::endl<< std::endl;

 
 
	waitKey(0);
	return 0;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第7张图片
从上面的运行结果我们可以看出,img_output的depth和channels和img_input的depth和channels相同,即矩阵的depth和channels都包含于type中。

4 利用成员函数convertTo()实现数据类型的转换

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
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;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第8张图片
可见实现了数据类型的转换,运行结果中的0和2具体代表的类型可查看上上一个示例代码(即本文中的3-1)。

5 与尺寸有关的操作

5-1 获取矩阵的行数或列数

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
	cv::Mat Image1( 10, 8, CV_8UC1, cv::Scalar(5) );
	// 矩阵的行数和列数获取
	std::cout << "Image1 row: " << Image1.rows << std::endl<< std::endl;
	std::cout << "Image1 col: " << Image1.cols << std::endl<< std::endl;

	return 0;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第9张图片

5-2 获取矩阵的尺寸(size)

代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
	cv::Mat Image1( 10, 8, CV_8UC1, cv::Scalar(5) );

	// 矩阵的尺寸(size)
	std::cout << "Image1的尺寸为: " << Image1.size() << std::endl<< std::endl;

	return 0;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第10张图片
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第11张图片

从上面的截图中我们可以看出,函数size()只是获取矩阵的宽度和高度(宽度值在前,高度值在后),而不会获取矩阵更高维度的值,比如通道数是不会获取的。

5-3 通过函数size()获取另一矩阵的尺寸来新建一个矩阵

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
int main( )
{
	cv::Mat Image1 = cv::imread("F:/material/images/P0005-BaoXiaofeng.jpg");
	cv::Mat Image2(Image1.size(), Image1.type());
	
	// 矩阵的尺寸(size)
	std::cout << "Image1的尺寸为: " << Image1.size() << std::endl<< std::endl;
	std::cout << "Image2 row: " << Image2.rows << std::endl<< std::endl;
	std::cout << "Image2 col: " << Image2.cols << std::endl<< std::endl;

	return 0;
}

OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第12张图片

5与6之间插一个:利用成员函数at()访问具体的像素值

这个的详细介绍见博文https://www.hhai.cc/thread-75-1-1.html 【打开页面后搜索“成员函数Mat:at()”】
要注意at的两个参数,第一个为行号,第二个为列号,即并不是按横坐标,纵坐标的顺序,而是按行号和列号的顺序。

6 通过成员函数row()获取矩阵的某行(与原矩阵共用内存空间)

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
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;
}

运行结果如下图所示:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第13张图片
从运行结果我们可以看,Image2和Image1是共用内存空间的,修改Image2的值会影响Image1第0行的值,而修改Image1中第0行的值也会影响到Image2。

7 通过成员函数col()获取矩阵的某列(与原矩阵共用内存空间)

这个和上一个示例其实是一样的,只是把上一个示例中的row()改成col(),其它完全一样,也是与原矩阵共用内存空间。
示例代码如下:

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

8-1 通过成员函数rowRange()获取矩阵的某几行(与原矩阵共用内存空间)

这个和第5、第6是一样的使用方法,只是这个可以选取多行或多列,也是与原矩阵共用内存空间。
函数rowRange()的原型如下:

Mat cv::Mat::rowRange(	int 	startrow,
						int 	endrow 
					)	const

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

std::cout << Image1.rowRange(1,3) << std::endl;

8-2 通过成员函数colRange()获取矩阵的某几列(与原矩阵共用内存空间)

这个和上一个示例其实是一样的,只是把上一个示例中的rowRange()改成colRange(),其它完全一样,也是与原矩阵共用内存空间。
示例代码如下:

std::cout << Image1.colRange(2,4) << std::endl;

9 利用Mat::operator()(const Rect& roi) const 选择感兴趣矩形区域ROI(深拷贝ROI和浅拷贝ROI)

注意:上面标题中的operator()表示Mat类对符号()的运算符重载,关于运算符重载,可以参见我的另一篇博文,链接 https://www.hhai.cc/thread-81-1-1.html
关于上面标题中const的含义,可以参见我的另一篇博文,链接:https://www.hhai.cc/thread-82-1-1.html

深拷贝ROI区域的示例代码如下:

//利用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。
区域(100, 180, 150, 50)代表的矩形区域是:
矩形区域左上角顶点的坐标为(100, 180)
矩形区域在x方向上的长度为150;
矩形区域在y方向上长度为180;

浅拷贝ROI区域的示例代码如下:

#include 

#include 

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);
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第14张图片
从上面的运行结果来看,对浅拷贝对象A1_roi的修改也会影响到A1中相应元素的值。

9-附1 将一个矩阵(图像)复制到另一矩阵(图像)的指定区域(ROI)【深拷贝】

示例代码如下:

#include 

#include 

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.at<uchar>(1, 1) = 5; //这是为了测试看是不是深拷贝

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

	return(0);
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第15张图片

10 矩阵内部的行运算

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
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;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第16张图片

11 矩阵内部的列运算

这个和上一个示例其实是一样的,只是把上一个示例中的row()改成col(),其它完全一样。
示例代码如下:

Image1.col(0) = Image1.col(2) * 2;

12 利用函数clone()创建矩阵或矩阵子矩阵的副本(深拷贝,不与原矩阵共用内存空间)

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
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;
}

运行结果如下:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第17张图片

13 利用函数copyTo()复制矩阵到另一矩阵(深拷贝,不与原矩阵共用内存空间)

示例代码如下:

#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include 
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;
}

运行结果如下图所示:
OpenCV的Mat类对象的初始化、属性调整、属性获取、基本操作示例代码积累_第18张图片
从上面的运行结果我们可以看出函数clone()和函数copyTo()在使用上及效果上几乎是一样的,事实上,这两个函数在使用效果上几乎也是没有差别的。它们都不与原矩阵共用内存空间。
它们俩的细微差别如下:
clone 是完全的深拷贝,在内存中申请新的空间。
copyTo 也是深拷贝,但是否申请新的内存空间,取决于dst矩阵头中的大小信息是否与src一至,若一致则只深拷贝并不申请新的空间,否则先申请空间后再进行拷贝。

14 利用MAT类成员函数at()访问矩阵元素的数据值

类成员函数at()的详细介绍请参看我的另一篇博文,链接如下:
https://www.hhai.cc/thread-75-1-1.html【进入页面后搜索“成员函数Mat:at()”】

你可能感兴趣的:(图像处理原理,工具,代码,不断积累的博文,Mat类的对象初始化,Mat类基本操作)