cv::Mat 初始化 与 访问

cv::Mat 初始化

一、无数据拷贝的cv::Mat的定义和初始化

1、默认形式

cv::Mat m;

2、指定类型和大小(行列)的二维数组

cv::Mat m(int rows, int cols, int type);

3、有初始化值的指定类型和大小(行列)的二维数组

cv::Mat m(int rows, int cols, int type, const Scalar& s);

4、使用预先存在数据定义的指定类型和大小(行列)的二维数组

cv::Mat m(int rows, int cols, int type, void* data, size_t step = AUTO_STEP);

5、指定大小(size)和类型的二维数组

cv::Mat m(cv::Size sz, int type, const Scalar& s);

6、使用预先存在的数据定义的指定大小(size)和类型的二维数组

cv::Mat m(cv::Size sz, int type, void* data, size_t step = AUTO_STEP);

7、指定类型的多维数组

cv::Mat m(int ndims, const int* sizes, int type);

8、有初始化值的指定类型多维数组

cv::Mat m(int ndims, const int* sizes, int type, const Scalar& s);

9、使用预先存在的数据定义的指定类型的多维数组

cv::Mat m(int ndims, const int* sizes, int type, void* data, size_t step = AUTO_STEP);

二、从其他cv::Mat进行数据拷贝的定义和初始化

1、拷贝构造形式

cv::Mat m(const cv::Mat& mat);

2、指定行列范围的拷贝构造

cv::Mat m(const cv::Mat& mat, const cv::Range& rows, const cv::Range& cols);

3、指定ROI的拷贝构造

cv::Mat m(const cv::Mat& mat, const cv::Rect& roi);

4、使用多维数组中指定范围内的数据的拷贝构造

cv::Mat(const cv::Mat& mat, const cv::Range* ranges);

三、使用OpenCV中的模板进行定义和初始化

1、使用cv::Vec定义相同类型、大小为n的一维数组

cv::Mat m(const cv::Vec<T, n>& vec, bool = copyData = true);

2、使用cv::Matx定义相同类型、大小为mxn的二维数组

cv::Mat(const cv::Matx<T, m, n>& vec, bool copyData = true);

3、使用STL vector定义相同类型的一维数组

cv::Mat(const std::vector& vec, bool copyData = true);

四、直接使用静态函数创建cv::Mat

1、使用zeros()函数定义指定大小和类型的cv::Mat(全为0)

cv::Mat m = cv::Mat::zeros(int rows, int cols, int type);

2、使用ones()函数定义指定大小和类型的cv::Mat(全为0)

cv::Mat m = cv::Mat::ones(int rows, int cols, int type);

3、使用eye()函数定义指定大小和类型的cv::Mat(恒等矩阵)

cv::Mat m = cv::Mat::eye(int rows, int cols, int type);

完整代码

#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/types_c.h"

void demo1() {
    /*
    1...
    */
    cv::Mat m0;

    /*
    2、指定类型和大小(行列)的二维数组
    cv::Mat m1(int rows, int cols, int type);
    */
    cv::Mat m1(1080, 1920, CV_8UC3);

    /*
    3、有初始化值的指定类型和大小(行列)的二维数组
    cv::Mat m(int rows, int cols, int type, const Scalar& s);
    */
    cv::Mat m2(1080, 1920, CV_8UC3, cv::Scalar(100, 1, 1));


    /*
    4、使用预先存在数据定义的指定类型和大小(行列)的二维数组
    cv::Mat m(int rows, int cols, int type, void* data, size_t step = AUTO_STEP);
    */
    char* data = new char[15];
    cv::Mat m3(3, 5, CV_8UC1, data);
    std::cout << m3 << std::endl;

    cv::Mat m4(1, 5, CV_8UC3, data);
    std::cout << m4 << std::endl;


    /*
    5、指定大小(size)和类型的二维数组
    cv::Mat m(cv::Size sz, int type, const Scalar& s);
    */
    cv::Mat m5(cv::Size(10, 10), CV_8UC3, cv::Scalar(1, 2, 3));
    std::cout << m5 << std::endl;


    /*
    6、使用预先存在的数据定义的指定大小(size)和类型的二维数组
    cv::Mat m(cv::Size sz, int type, void* data, size_t step = AUTO_STEP);
    */
    cv::Mat m6(cv::Size(3, 5), CV_8UC1, data);
    std::cout << m6 << std::endl;

    /*
    7、指定类型的多维数组
    cv::Mat m(int ndims, const int* sizes, int type);
    */
    int size[3] = { 3, 2, 2 };
    cv::Mat m7(3, size, CV_8UC1);


    /*
    8、有初始化值的指定类型多维数组
    cv::Mat m(int ndims, const int* sizes, int type, const Scalar& s);
    */
    int matSize[] = { 5,8,10 };//每一维元素的个数:8:行,10:列
    cv::Mat m8(3, matSize, CV_16UC3, cv::Scalar::all(0));
    printf("\n///求step[i]的大小:每一维元素的大小(单位字节)//\n");
    printf("step[0]:%d\n", m8.step[0]);//480:面的大小(第一维)
    printf("step[1]:%d\n", m8.step[1]);//60:线的大小(第二维)
    printf("step[2]:%d\n", m8.step[2]);//6:点的大小(第三维)


    /*
    9、使用预先存在的数据定义的指定类型的多维数组
    cv::Mat m(int ndims, const int* sizes, int type, void* data, size_t step = AUTO_STEP);
    */
    int matSize2[] = { 2,2,2 };//每一维元素的个数:8:行,10:列
    char* data2 = new char[8];
    cv::Mat m9(3, matSize2, CV_8UC1, data2);
    printf("\n///求step[i]的大小:每一维元素的大小(单位字节)//\n");
    printf("step[0]:%d\n", m9.step[0]);//480:面的大小(第一维)
    printf("step[1]:%d\n", m9.step[1]);//60:线的大小(第二维)
    printf("step[2]:%d\n", m9.step[2]);//6:点的大小(第三维)
}

void demo2() {
    char* data = new char[15];
    cv::Mat m0(3, 5, CV_8UC1, data);
    std::cout << m0 << std::endl;

    /*
      1、拷贝构造形式
    cv::Mat m(const cv::Mat& mat);
    */
    cv::Mat m1(m0);

    /*
    2、指定行列范围的拷贝构造
    cv::Mat m(const cv::Mat& mat, const cv::Range& rows, const cv::Range& cols);
    */
    cv::Mat m2(m0, cv::Range(1,2), cv::Range(1,3));

    /*
    3、指定ROI的拷贝构造
    cv::Mat m(const cv::Mat& mat, const cv::Rect& roi);
    */
    cv::Mat m3(m0, cv::Rect(1,1, 2,2));
    std::cout << m3.size() << std::endl;

    /*
    4、使用多维数组中指定范围内的数据的拷贝构造
    cv::Mat(const cv::Mat& mat, const cv::Range* ranges);
    */
    int matSize[] = { 5,8,10 };//每一维元素的个数:8:行,10:列
    cv::Mat mm(3, matSize, CV_16UC3, cv::Scalar::all(0));
    cv::Range* ranges = new cv::Range[3]{cv::Range(1,2), cv::Range(1,3), cv::Range(1,4)};
    cv::Mat m4(mm, ranges);
    printf("step[0]:%d\n", m4.step[0]);//480:面的大小(第一维)
    printf("step[1]:%d\n", m4.step[1]);//60:线的大小(第二维)
    printf("step[2]:%d\n", m4.step[2]);//6:点的大小(第三维)
}


//三、使用OpenCV中的模板进行定义和初始化
void demo3() {
    /*
    1、使用cv::Vec定义相同类型、大小为n的一维数组
    cv::Mat m(const cv::Vec<T, n>& vec, bool = copyData = true);
    */
    cv::Vec<float, 10> data1{ 1,2,3,4,5, 6,7,8,9,10 };
    cv::Mat m1(data1, true);
    std::cout << m1 << std::endl;

    /*
    2、使用cv::Matx定义相同类型、大小为mxn的二维数组
    cv::Mat(const cv::Matx<T, m, n>& vec, bool copyData = true);
    */
    cv::Matx<float, 2, 4> data2{ 1,2,3,4,5,6,7,7 };
    cv::Mat m2(data2, true);
    std::cout << m2 << std::endl;

    /*
    3、使用STL vector定义相同类型的一维数组
    cv::Mat(const std::vector<T>& vec, bool copyData = true);
    */
    std::vector<float> vec{1, 2, 3, 4, 5, 6};
    cv::Mat m3(vec, true);
    std::cout << m3 << std::endl;
}


//四、直接使用静态函数创建cv::Mat
void demo4() {
    /*
    1、使用zeros()函数定义指定大小和类型的cv::Mat(全为0)
    cv::Mat m = cv::Mat::zeros(int rows, int cols, int type);
    */
    cv::Mat m1 = cv::Mat::zeros(10, 10, CV_8UC1);


    /*
    2、使用ones()函数定义指定大小和类型的cv::Mat(全为0)
    cv::Mat m = cv::Mat::ones(int rows, int cols, int type);
    */
    cv::Mat m2 = cv::Mat::ones(10, 10, CV_8UC1);

    /*
    * 3、使用eye()函数定义指定大小和类型的cv::Mat(恒等矩阵)
    cv::Mat m = cv::Mat::eye(int rows, int cols, int type);
    */
    cv::Mat m3 = cv::Mat::eye(10, 10, CV_8UC1);
    std::cout << m3 << std::endl;
}

int main()
{
    // demo1();
    // demo2();
    // demo3();
    demo4();
    return 0;
}

cv::Mat 访问

单通道灰度图数据存放格式:
在这里插入图片描述

多通道的图像中,每列并列存放通道数量的子列,如RGB三通道彩色图:
在这里插入图片描述
opencv中,由于使用Mat.at访问数据时,必须正确填写相应的数据类型,因此必须弄清楚opencv中的数据类型与我们常用数据类型一一对应关系。

单通道访问 Mat:

Mat_---------CV_8U
Mat_-----------CV_8S
Nat_---------CV_16S
Mat_--------CV_16U
Mat_-----------CV_32S
Mat_----------CV_32F
Mat_--------CV_64F

下面主要记录三种常见的访问Mat的方式:1.at访问 2.ptr访问 3.data访问
Mat中不管是以at访问还是ptr访问,都是行优先 ,先Y轴后X轴(即先行后列)

//***方法1:************************************************************
t = (double)getTickCount();
Mat img1(1000, 1000, CV_32F);

for (int i=0; i<1000; i++)
{
	for (int j=0; j<1000; j++)
	{
		img1.at<float>(i,j) = 3.2f;
	}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());

//***方法2************************************************************
t = (double)getTickCount();
Mat img2(1000, 1000, CV_32F);

for (int i=0; i<1000; i++)
{
	for (int j=0; j<1000; j++)
	{
		img2.ptr<float>(i)[j] = 3.2f;
	}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());

//***方法3************************************************************
t = (double)getTickCount();
Mat img3(1000, 1000, CV_32F);
float* pData = (float*)img3.data;

for (int i=0; i<1000; i++)
{
	for (int j=0; j<1000; j++)
	{
		*(pData) = 3.2f;
		pData++;
	}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());

//***方法3************************************************************
t = (double)getTickCount();
Mat img4(1000, 1000, CV_32F);

for (int i=0; i<1000; i++)
{
	for (int j=0; j<1000; j++)
	{
		((float*)img3.data)[i*1000+j] = 3.2f;
	}
}
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());

//***方法3******加强版************************************************
t = (double)getTickCount();
Mat img5(1000, 1000, CV_32F);
float *pData1;
for (int i=0; i<1000; i++) 
{ 
	pData1=img5.ptr<float>(i);
	for (int j=0; j<1000; j++) 
	{ 
		pData1[j] = 3.2f; 
	} 
} 
t = (double)getTickCount() - t;
printf("in %gms\n", t*1000/getTickFrequency());
多通道Mat访问

用at进行多通道访问,对应的数据类型如下:
typedef Vec<uchar, 2> Vec2b; //无符号双通道 CV_8U:0~255
typedef Vec<uchar, 3> Vec3b; //无符号3通道
typedef Vec<uchar, 4> Vec4b;
typedef Vec<short, 2> Vec2s; //short型双通道 CV_16S:-32768~32767
typedef Vec<short, 3> Vec3s;
typedef Vec<short, 4> Vec4s;
typedef Vec<int, 2> Vec2i; //整型双通道 CV_32S:-2147483648~2147483647
typedef Vec<int, 3> Vec3i;
typedef Vec<int, 4> Vec4i;
typedef Vec<float, 2> Vec2f; //浮点型双通道 CV_32F:1.1810-38~3.401038
typedef Vec<float, 3> Vec3f;
typedef Vec<float, 4> Vec4f;
typedef Vec<float, 6> Vec6f;
typedef Vec<double, 2> Vec2d; //double型双通道 CV_64F:2.2310-308~1.7910308
typedef Vec<double, 3> Vec3d;
typedef Vec<double, 4> Vec4d;
typedef Vec<double, 6> Vec6d;

示例程序,创建及访问双通道Mat

#include <opencv2/core/core.hpp>
#include <iostream>
 
using namespace std;
using namespace cv;
 
int main()
{
	int i, j;
	Mat dimg(3, 5, CV_16SC2,Scalar(-5,5));//构造一个3*5的short型双通道矩阵
       cout << "原矩阵" << endl << dimg << endl;
 	short int a=1,b=15;
	for (i = 0; i < dimg.rows; i++)
	{
		for (j = 0; j < dimg.cols; j++)
		{
			dimg.at<Vec2s>(i, j)[0] = a;//at<type>其中type由矩阵的类型确定
			dimg.at<Vec2s>(i, j)[1] = b;
		}
	}
 
	cout << "改变后矩阵" << endl << dimg << endl;
	system("pause");
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI_潜行者

赐予我力量吧

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值