Mat对象构造函数与复制
//构造函数
Mat()
Mat(int rows,int cols, int type) // rows 行数
Mat(Size size,int type) // cols 列数
Mat(int rows,int cols,const Scalar &s) // Size 图片大小(x,y)
Mat(int ndims, const int *sizes, int type) // ndims 矩阵维度
Mat(int ndims, const int *sizes, int type,const Scalar &s ) // 颜色 Scalar (B,G,R)
//常用方法
void copyTo(Mat mat) //复制到传入的Mat
void convertTo(Mat dst,int type) //生成新的Mat,指定其数据类型
Mat clone() //复制后,返回新的Mat
int channels() //返回通道数
int depth() //返回数据位深度
bool empty() //判断数据是否为空
uchar* ptr(i = 0) //返回图片像素指针,i为行索引
图像创建与矩阵创建
Mat img(100,100,CV_8UC3,Scale(0,0,255));
// 宽 ,高,数据类型,填充颜色(需要与数据类型对应)
//8UC3 -> 8:位深位8bit UC:uchar 3:三个通道
int size[3] = {2,2,2}; //矩阵长,宽,高
Mat L(3,sz,CV_8UC1,Scale(0,0,255));
//矩阵维度,矩阵形状,数据类型,填充数据
Mat ml;
ml.creat(L.size(),L.type());
//用creat创建矩阵
ml = Scalar(0,0,255);
//再用Scalar来填充
//定义小数组
Mat kernel = (Mat_<float>(3,3) << 0,-1,0,-1,5,-1,0,-1,0);
//创建特殊矩阵
Mat mz = Mat::zeros(src.size,src.type);
Mat eye = Mat::eye(src.size,src.type);
部分复制与完全复制
- 部分复制:一般情况下只会复制Mat对象的头和指针部分,不会复制数据部分
- 完全复制:如果想要把Mat对象的头部和数据部分一起复制,可以通过copyTo和clone实现
Mat A = imread(imgFilePath);
//部分复制,浅拷贝
Mat B = A;
Mat C(A);
//完全复制,深拷贝
Mat D = A.clone();
Mat E ; A.copyTo(E);
图像相关操作
读写像素
//单通道
Scalar intensity = img.at<uchar>(y,x);
//三通道
Vec3f intensity = img.at<Vec3f>(y,x);
//Vec3f: Vec 返回一个向量 3 通道数,即Vec的大小 f 数据类型
转灰度的几种方式
- 采用公式转换
- 取R,G,B中的最大值
- 取R,G,B中的最小值
Mat dst;
src.convertTo(dst,CV_32F);
//改变数据类型 CV_32F
//改变颜色空间 COLOR_BGR2GRAY
代码与实践
#include <iostream>
#include <math.h>
#include <opencv2/opencv.hpp>
using namespace cv;
using namespace std;
int main(int argc, char* argv[])
{
Mat src = imread("1.jpg");
if (src.empty())
{
cout << "could not open image ..." << endl;
return -1;
}
Mat gray;
cvtColor(src, gray, COLOR_BGR2GRAY);
int rows = gray.rows;
int cols = gray.cols;
imshow("src", src);
imwrite("src.jpg", src);
imshow("gray", gray);
imwrite("gray.jpg", gray);
Mat ingray = gray.clone();
//单通道
for (int col = 0; col < cols; col++)
{
for (int row = 0; row < rows; row++)
{
int g = gray.at<uchar>(row, col);
ingray.at<uchar>(row, col) = 255 - g;
}
}
imshow("ingray", ingray);
imwrite("ingray_pix.jpg", ingray);
//三通道
Mat dst;
dst.create(src.size(), src.type());
int height = src.rows;
int width = src.cols;
int nc = src.channels();
Mat gray1(src.rows, src.cols, CV_8UC1);
Mat gray2(src.rows, src.cols, CV_8UC1);
gray1 = Scalar(0);
gray2 = Scalar(0);
for (int col = 0; col < cols; col++)
{
for (int row = 0; row < rows; row++)
{
if (nc == 1)
{
int t = gray.at<uchar>(row, col);
ingray.at<uchar>(row, col) = 255 - t;
}
else if(nc == 3)
{
int b = src.at<Vec3b>(row, col)[0];
int g = src.at<Vec3b>(row, col)[1];
int r = src.at<Vec3b>(row, col)[2];
dst.at<Vec3b>(row, col)[0] = 255 - b;
dst.at<Vec3b>(row, col)[1] = 255 - g;
dst.at<Vec3b>(row, col)[2] = 255 - r;
gray1.at<uchar>(row, col) = max(b, max(g, r));
gray2.at<uchar>(row, col) = min(b, min(g, r));
}
}
}
//取负片 同样的有bitwise_and,bitwise_nor,bitwise_or等对像素点的逻辑运算
Mat insrc1;
src.copyTo(insrc1);
bitwise_not(src, insrc1);
imshow("insrc_pix", dst);
imshow("insrc_bitwise",insrc1);
imshow("gray_min", gray1);
imshow("gray_max", gray2);
imwrite("insrc_pix.jpg", dst);
imwrite("insrc_bitwise.jpg", insrc1);
imwrite("gray_min.jpg", gray1);
imwrite("gray_max.jpg", gray2);
waitKey(0);
return 0;
}
src gray not_gray not_src_pix
not_src_bit gray_max gray_min