图片在C++中是作为矩阵Matrix进行处理对待的,通过Mat数据类型进行处理
 
 新建项目这里就不再赘述了哈,可以参考博文:零、环境搭建(第三部分Visula Studio中新建项目)
 我这边创建的项目名称为:1_31_matrix
为了养成良好的项目开发习惯,对于某些功能的实现都重新定义一个头文件,然后再创建一个新的文件去实现头文件中所定义的类中所有的方法,最后通过项目的主文件进行调用即可
一、创建头文件
在项目的头文件中,右击添加,新建项
 
 创建Mat对象头文件,我这边是mat_attribute.h
 
 该头文件声明了一个Matrices类(class Matrices),该类下面声明一个函数(void mat_create(Mat& image))
mat_attribute.h头文件内容如下:
#pragma once
#include <opencv2/opencv.hpp>
using namespace cv;
class Matrices {
	public:
		void mat_create(Mat& image);
};
二、实现头文件中创建的类中的方法
创建个文件,用于实现头文件中Matrices类中的mat_create函数
 我这个文件是:matrices.cpp
 
 
Ⅰ,新建图片
1,创建一张单颜色通道全为0的8×8图片
#include"mat_attribute.h",导入自定义的头文件
 #include <opencv2/opencv.hpp>,因为要显示图片,导入opencv
Mat::zeros(Size(8, 8), CV_8UC1)
 参数一:zeros(),全为零
 参数二:Size(8, 8),图片大小8×8
 参数三:CV_8UC1,8位(8)、无符号字符(unsigned char,UC)、单通道(1)
namedWindow("new_8*8*1_zeros", WINDOW_FREERATIO);,创建一个新的窗体命名为new_8*8*1_zeros,窗体显示为自适应WINDOW_FREERATIO
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::zeros(Size(8, 8), CV_8UC1);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*1_zeros", WINDOW_FREERATIO);
	imshow("new_8*8*1_zeros", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
2,创建一张三颜色通道全为0的8×8图片
同理,全为0的8×8三通图片就可以通过Mat::zeros(Size(8, 8), CV_8UC3);进行实现,这里需要注意是,图片以矩阵进行展示,竖着切,下面这个图应该可以很好的展示C++中mat通过二维数组进行展示的像素点值
 
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::zeros(Size(8, 8), CV_8UC3);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*3_zeros", WINDOW_FREERATIO);
	imshow("new_8*8*3_zeros", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
3,创建一张单颜色通道全为1的8×8图片
到这里可能会有同学根据第一个样例,比葫芦画瓢进行这个样例的改写了,Mat::ones(Size(8, 8), CV_8UC1);,没毛病!
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC1);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*1_ones", WINDOW_FREERATIO);
	imshow("new_8*8*1_ones", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
4,创建一张三颜色通道全为1的8*8图片
①,若通过ones进行创建三颜色通道全为1图片,仅仅给第一个通道全赋值为1而已,其余连个颜色通道像数值还是0
同理,比葫芦画瓢进行这个样例的改写了,Mat::ones(Size(8, 8), CV_8UC3);,有问题!!!!
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*3_ones", WINDOW_FREERATIO);
	imshow("new_8*8*3_ones", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
 可以看到,出现了问题,只有一个通道被赋值给了1,其他的俩通道还是0
②,通过直接给mat赋值的方法,也仅仅针对的是第一个颜色通道进行赋值,其他颜色通道数值仍为0
如果直接对这个mat赋值(y1 = 128;)的话,也仅仅针对的是第一个通道进行赋值
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	y1 = 128;
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*3_ones", WINDOW_FREERATIO);
	imshow("new_8*8*3_ones", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
③,Scalar()函数对三个通道赋值
y1 = Scalar(128,128,128);,该函数可以实现对三个颜色通道依次赋值,三个参数分别为BGR三颜色通道的值
 为了演示效果明显,采用灰度图(128,128,128)进行测试
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	y1 = Scalar(128,128,128);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	namedWindow("new_8*8*3_ones", WINDOW_FREERATIO);
	imshow("new_8*8*3_ones", y1);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
 该方法可以满足对三颜色通道全部进行设置的操作
Ⅱ,赋值操作(=)
赋值操作=,可以理解为浅拷贝,指向的是同一个对象
 y1 = Scalar(128,128,128);,可以看到y1是灰度图
 y2 = y1;,赋值之后y1和y2其实同一个内存数据
 y2 = Scalar(255,0,0);,改变y2时,y1也发生了改变,展示y1和y2时,都是蓝色的图片,可以理解为浅拷贝,都是同一个对象
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	y1 = Scalar(128,128,128);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	
	Mat y2;
	y2 = y1;
	y2 = Scalar(255,0,0);
	namedWindow("test1", WINDOW_FREERATIO);
	namedWindow("test2", WINDOW_FREERATIO);
	imshow("test1", y1);
	imshow("test2", y2);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
Ⅲ,clone()函数
clone()就是深拷贝了,是两个完全不同的对象
 y2 = y1.clone();,y1和y2是两个完全不同的对象了
 y2 = Scalar(255,0,0);,操作y2时对y1没有影响
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	y1 = Scalar(128,128,128);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	
	Mat y2;
	y2 = y1.clone();
	y2 = Scalar(255,0,0);
	namedWindow("test1", WINDOW_FREERATIO);
	namedWindow("test2", WINDOW_FREERATIO);
	imshow("test1", y1);
	imshow("test2", y2);
	waitKey(0);
	destroyAllWindows();
}

Ⅳ,copyTo()函数
这个和clone()函数类似,都是深拷贝,独立成不同的空间
 y1.copyTo(y2);,这里是y1拷贝给y2,将y1的内容全部独立开辟内存空间给y2,y1和y2是相互独立的
 y2 = Scalar(255,0,0),改变y2,y1没有影响
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat y1 = Mat::ones(Size(8, 8), CV_8UC3);
	y1 = Scalar(128,128,128);
	std::cout << "width:" << y1.cols << " height:" << y1.rows << " channels:" << y1.channels() << std::endl;
	std::cout << y1 << std::endl;
	
	Mat y2;
	y1.copyTo(y2);//y1拷贝给y2,此处y1和y2一样,但是是两个完全独立的对象,深拷贝
	y2 = Scalar(255,0,0);
	
	namedWindow("test1", WINDOW_FREERATIO);
	namedWindow("test2", WINDOW_FREERATIO);
	imshow("test1", y1);
	imshow("test2", y2);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
Ⅴ,构建mask掩膜操作
掩膜操作不陌生吧,Mat也可以进行构建mask,也方便opencv之后的一系列操作
#include"mat_attribute.h"
#include <iostream>
#include <opencv2/opencv.hpp>
void Matrices::mat_create() {
	Mat mask = (Mat_<char>(3, 3) << 0, -1, 0, 
		                           -1, 5, -1, 
		                           0, -1, 0);
	std::cout << "width:" << mask.cols << " height:" << mask.rows << " channels:" << mask.channels() << std::endl;
	std::cout << mask << std::endl;
	namedWindow("mask", WINDOW_FREERATIO);
	imshow("mask", mask);
	waitKey(0);
	destroyAllWindows();
}
效果图如下:
 
三、主函数文件
同理,创建一个cpp文件,我这里以yy_main.cpp为例
 
 
 #include "mat_attribute.h",导入自定义的头文件
 Matrices yy;,对这个类进行赋予对象
 yy.mat_create();,调用这个类中的mat_create()函数
#include <opencv2/opencv.hpp>
#include <iostream>
#include "mat_attribute.h"
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
	Matrices yy;
	yy.mat_create();
	return 0;
}


















