C++ opencv之图像对象的创建与赋值

文章目录

  • 一、引入
  • 二、克隆与拷贝
  • 三、创建图像

一、引入

首先我们来看一下Mat 的基本结构
C++ opencv之图像对象的创建与赋值_第1张图片
其中数据部分为像素的值的一个集合,头部就是包含图像的一个属性,比如大小、宽高、类型、通道数等等。

在对他进行赋值操作的时候,只是相当于把内存的指针重新指向了原来的数据,本质上还是同一个DataBlock,当进行克隆或者拷贝操作的时候,就会把这个Mat中所有的数据复制一份,以供使用。

二、克隆与拷贝

还是跟以前一样,采用多文件调用的方式。声明函数的demo放在quickopencv.h文件里,实现放在quickdemo.cpp文件里,后续用到的时候只显示quickdemo.cpp中的代码。
test.cpp

#include 
#include 
#include 


using namespace std;
using namespace cv;

int main(int argc, char** argv)
{
	//获取文件图片
	Mat src = imread("C:\\Users\\Dell\\Desktop\\picture\\3.jpg");
	if (src.empty())
	{
		printf("could not load image...\n");
		return -1;
	}
	//namedWindow("输入窗口",WINDOW_FREERATIO);
	imshow("输入窗口", src);

	QuickDemo qd;
	//qd.addWeighted_Demo(src);
	qd.Mat_creation_Demo(src);
	//qd.pixel_visit_Demo(src);
	//qd.operators_Demo(src);
	waitKey(0);
	destroyAllWindows();
	return 0;
}

quickopencv.h:

#pragma once

#include ;
using namespace cv;

class QuickDemo
{
public:
	void Mat_creation_Demo(Mat &image);
};

#include 
#include 
using namespace std;
//第三讲 图像对象的创建
void QuickDemo::Mat_creation_Demo(Mat &image)
{
	Mat m1, m2;
	m1 = image.clone();//克隆
	image.copyTo(m2);//拷贝
	imshow("图像1", m1);
	imshow("图像2", m2);
}

这里显示出m1,m2的图片,从图片的角度来看是没有区别的。

我们来看一下函数原型:
首先是copyto:

void copyTo( OutputArray m ) const;
 
 参数一:目标矩阵(输出的图片)。 
 如果在操作之前没有适当的大小或类型,则重新分配。

下来是clone:

inline Mat Mat::clone() const
{
    Mat m;
    copyTo(m);
    return m;
}

clone 函数我们可以先看一下它的定义,它是一个内联函数,返回值为 Mat,函数体部分调用的还是 copyTo() 函数。

区别为:

clone是把所有的都复制过来,也就是说不论你是否设置Roi,Coi等影响copy的参数,clone都会原封不动的克隆过来。

copy就不一样,只会复制ROI区域等。

用clone复制之后,源图像在内存中消失后,复制的图像也变了,而用copy复制,源图像消失后,复制的图像不变。

三、创建图像

首先我们来创建一个空白图像:

void QuickDemo::Mat_creation_Demo(Mat &image)
{
	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC1);//8位unsigned char类型的单通道矩阵
	std::cout << m3 << std::endl;
}

C++ opencv之图像对象的创建与赋值_第2张图片
这里顺道介绍一下CV_8UC1中各项参数的含义:

1、bit_depth:比特数,有代表8bite\16bite\32bite\64bite

8表示你所创建的储存图片的Mat对象中,每个像素点在内存空间所占的空间大小8bite。
2、S|U|F

S: signed int,即有符号整型。
U: unsigned int,即无符号整型。
F: float,单精度浮点型。
3、:代表所存储的图片的通道数。

若为1:grayImg灰度图像,即单通道图像。
若为2:RGB彩色图像,即3通道图像。
若为3:带Alpha通道的RGB彩色图像,即4通道图像。

将上述的代码修改一下:

void QuickDemo::Mat_creation_Demo(Mat &image)
{
	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);//8位unsigned char类型的3通道矩阵
	std::cout << m3 << std::endl;
}

C++ opencv之图像对象的创建与赋值_第3张图片

可以看出原矩阵从8×8变为了24×8,因为原来是单通道,而现在为3通道,代表着每个像素点包含了三个像素值,可以说明图像在Mat上面真正的宽度等于通道数乘以Mat定义矩阵的宽度,那么怎么获取宽度呢?

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::zeros(Size(8, 8), CV_8UC3);
	std::cout << "width: " << m3.cols << "height: " << m3.rows << "channels: " << m3.channels() << std::endl;
}

C++ opencv之图像对象的创建与赋值_第4张图片
可以看出 宽度为8,高度为8,通道数为3 ,真正的宽度为宽度乘以通道数即24。

上面创建的是每个通道都为0的图,也可以创建通道都为1的图:

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::ones(Size(8, 8), CV_8UC1);
	std::cout << m3 << std::endl;
}

C++ opencv之图像对象的创建与赋值_第5张图片
上面的图是单通道,每个通道都为1的图,那么每个通道都为1的图能用在三通道的情况吗,答案是不可以,我们来看输出结果:

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::ones(Size(8, 8), CV_8UC3);
	std::cout << m3 << std::endl;

C++ opencv之图像对象的创建与赋值_第6张图片
结果就是每个像素点的第一个通道为1,其余通道都为0.
zeros 和ones就是我们常用的两个初始化方法。

其实我们也可以对m3赋值,来改变他的第一个通道的值。

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::ones(Size(8, 8), CV_8UC3);
	m3 = 127;
	std::cout << m3 << std::endl;

C++ opencv之图像对象的创建与赋值_第7张图片
结果就是每一个像素点第一个值变为127了。

那如何将每个通道的值都赋值为127呢?
加上这一句代码:

m3=Scalar(127, 127, 127);

输出结果为:
C++ opencv之图像对象的创建与赋值_第8张图片
可以看到结果为 每个像素的三个通道都被赋值为127。

我们可以把我们创建的图像显示出来:

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
	m3=Scalar(255, 0, 0);
	std::cout << "width: " << m3.cols <<" "<< "height: " << m3.rows << " " << "channels: " << m3.channels() << std::endl;
	imshow("创建图像", m3);
}

C++ opencv之图像对象的创建与赋值_第9张图片
C++ opencv之图像对象的创建与赋值_第10张图片
一个宽度高度都为400,通道数为3 的图像。

这里我们再次用到clone

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
	m3=Scalar(255, 0, 0);
	std::cout << "width: " << m3.cols <<" "<< "height: " << m3.rows << " " << "channels: " << m3.channels() << std::endl;
	Mat m4=m3;
	m4=Scalar(0,0,255);
	imshow("创建图像", m3);
}

输出结果为:
C++ opencv之图像对象的创建与赋值_第11张图片
因为我们这里把m3赋值给m4了,所以对m4进行操作,也就是对m3进行操作,所以输出m3输出就是红色。

我们再来试一下clone

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
	m3=Scalar(255, 0, 0);
	std::cout << "width: " << m3.cols <<" "<< "height: " << m3.rows << " " << "channels: " << m3.channels() << std::endl;
	Mat m4=m3.clone();
	m4=Scalar(0,0,255);
	imshow("创建图像", m3);
}

C++ opencv之图像对象的创建与赋值_第12张图片
可以看出来,这里我们用m4克隆m3,再去操作m4,再去输出m3就还是以前的m3。

再来试一下copyto

void QuickDemo::Mat_creation_Demo()
{
	Mat m3 = Mat::zeros(Size(400, 400), CV_8UC3);
	m3=Scalar(255, 0, 0);
	std::cout << "width: " << m3.cols <<" "<< "height: " << m3.rows << " " << "channels: " << m3.channels() << std::endl;
	Mat m4;
	m3.copyTo(m4);
	m4 = Scalar(0, 0, 255);
	imshow("m3", m3);
	imshow("m4", m4);
}

C++ opencv之图像对象的创建与赋值_第13张图片
可以看到,m3.copyTo(m4),m4 = Scalar(0, 0, 255),复制操作过后,输出m3,m4,m4为红色图像,但是对m3是没有影响的,依旧跟上面代码中设定的一样,为蓝色图。

最后再来输出一个矩阵:

void QuickDemo::Mat_creation_Demo()
{
Mat kernel = (Mat_<char>(3, 3) << 

		0, 1, 0,
		1, 2, 3,
		4, 5, 6);
	std::cout << "kernel:"<< std:: endl;
	std::cout << kernel<<std::endl;
	
}

C++ opencv之图像对象的创建与赋值_第14张图片
这篇博客就讲这么多吧,主要是图像对象的创建与赋值的知识。

加油吧,阿超没有蛀牙!

你可能感兴趣的:(OpenCV,c++,计算机视觉)