首先我们来看一下Mat 的基本结构
其中数据部分为像素的值的一个集合,头部就是包含图像的一个属性,比如大小、宽高、类型、通道数等等。
在对他进行赋值操作的时候,只是相当于把内存的指针重新指向了原来的数据,本质上还是同一个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;
}
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;
}
可以看出原矩阵从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;
}
可以看出 宽度为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;
}
上面的图是单通道,每个通道都为1的图,那么每个通道都为1的图能用在三通道的情况吗,答案是不可以,我们来看输出结果:
void QuickDemo::Mat_creation_Demo()
{
Mat m3 = Mat::ones(Size(8, 8), CV_8UC3);
std::cout << m3 << std::endl;
结果就是每个像素点的第一个通道为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;
那如何将每个通道的值都赋值为127呢?
加上这一句代码:
m3=Scalar(127, 127, 127);
输出结果为:
可以看到结果为 每个像素的三个通道都被赋值为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);
}
这里我们再次用到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);
}
输出结果为:
因为我们这里把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);
}
可以看出来,这里我们用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);
}
可以看到,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;
}
加油吧,阿超没有蛀牙!