图片在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;
}