M a t 对 象 及 其 基 本 操 作 Mat对象及其基本操作Mat对象及其基本操作
1.Mat对象
Mat的定义
Mat(matrix矩阵):图像文件的内存数据对象
Mat:header (宽、高、通道数等信息)+ data(图像数据信息)

数据类型和通道信息
| 图像深度 | 对应数据类型 |
|---|---|
| CV_8U | 8位无符号-字节类型 |
| CV_8S | 8位有符号-字节类型 |
| CV_16U | 16位无符号类型 |
| CV_16S | 16位有符号类型 |
| CV_32S | 32整形数据类型 |
| CV_32F | 32位浮点数类型 |
| CV_64F | 64位双精度类型 |
| 单通道 | 双通道 | 三通道 | 四通道 |
|---|---|---|---|
| CV_8UC1 | CV_8UC2 | CV_8UC3 | CV_8UC4 |
| CV_32SC1 | CV_32SC2 | CV_32SC3 | CV_32SC4 |
| CV_32FC1 | CV_32FC2 | CV_32FC3 | CV_32FC4 |
| CV_64FC1 | CV_64FC2 | CV_64FC3 | CV_64FC4 |
| CV_16SC1 | CV_16SC2 | CV_16SC3 | CV_16SC4 |
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/cats.jpg", IMREAD_COLOR); // IMREAD_COLOR:加载为3通道彩色图像
if (src.empty()) {
printf("image is empty!!!");
return -1;
}
namedWindow("image", WINDOW_FREERATIO); // WINDOW_NORMAL:可任意设置图像大小
imshow("image", src);
int width = src.cols;
int height = src.rows;
int dim = src.channels();
printf("width : %d,height:%d,channels: %d",width,height,dim);
waitKey(0);
destroyAllWindows();
return 0;
}

2 属性与操作
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/cats.jpg", IMREAD_COLOR); // IMREAD_COLOR:加载为3通道彩色图像
if (src.empty()) {
printf("image is empty!!!");
return -1;
}
namedWindow("image", WINDOW_FREERATIO); // WINDOW_NORMAL:可任意设置图像大小
imshow("image", src);
int width = src.cols; // 宽
int height = src.rows; // 高
int dim = src.channels(); // 通道数
int img_depth = src.depth();
int img_type = src.type();
printf("width : %d,height:%d,channels: %d,depth:%d,type: %d",width,height,dim, img_depth, img_type);
waitKey(0);
destroyAllWindows();
return 0;
}

数据类型和通道类型:(0,16)和下表对应:CV_8U、 CV_8UC3
| 图像深度 | 对应数据类型 |
|---|---|
| CV_8U | 8位无符号-字节类型 |
| CV_8S | 8位有符号-字节类型 |
| CV_16U | 16位无符号类型 |
| CV_16S | 16位有符号类型 |
| CV_32S | 32整形数据类型 |
| CV_32F | 32位浮点数类型 |
| CV_64F | 64位双精度类型 |
| 单通道 | 双通道 | 三通道 | 四通道 |
|---|---|---|---|
| CV_8UC1 | CV_8UC2 | CV_8UC3 | CV_8UC4 |
| CV_32SC1 | CV_32SC2 | CV_32SC3 | CV_32SC4 |
| CV_32FC1 | CV_32FC2 | CV_32FC3 | CV_32FC4 |
| CV_64FC1 | CV_64FC2 | CV_64FC3 | CV_64FC4 |
| CV_16SC1 | CV_16SC2 | CV_16SC3 | CV_16SC4 |
3 创建
- 3.1 创建空白Mat对象
- 从现有图像创建
- 创建填充值的Mat对象
- 创建单通道与多通道Mat对象
- 遍历与访问像素值
3.1 创建空白Mat对象
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//- 创建空白Mat对象
Mat t1 = Mat(256, 256, CV_8SC1);
t1 = Scalar(0);
imshow("t1", t1);
Mat t2 = Mat(256, 256, CV_8SC3);
t2 = Scalar(0, 255, 0);
imshow("t2", t2);
//- 从现有图像创建
//- 创建填充值的Mat对象
//- 创建单通道与多通道Mat对象
//- 遍历与访问像素值
waitKey(0);
destroyAllWindows();
return 0;
}


Mat(Size(512,512), CV_8SC1);
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//- 创建空白Mat对象
Mat t1 = Mat(Size(512,512), CV_8SC1);
t1 = Scalar(0);
imshow("t1", t1);
Mat t2 = Mat(Size(512, 512), CV_8SC3);
t2 = Scalar(0, 255, 0);
imshow("t2", t2);
waitKey(0);
destroyAllWindows();
return 0;
}
Mat::zeros(Size(256,256),CV_8SC1);
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
//- 创建空白Mat对象
Mat t1 = Mat::zeros(Size(256,256),CV_8SC1);
imshow("t1", t1);
waitKey(0);
destroyAllWindows();
return 0;
}
3.2 从现有图像创建
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/cats.jpg", IMREAD_COLOR); // IMREAD_COLOR:加载为3通道彩色图像
if (src.empty()) {
printf("image is empty!!!");
return -1;
}
// create from src
// 修改t1即修改src,t2 clone t1,修改t1 所以 t2也会变
// 但是修改克隆t1的t2改变,t1不会变
Mat t1 = src;
t1 = Scalar(0, 255, 0);
Mat t2 = src.clone(); // src.copyTo(t2)
imshow("t2", t2);
// 创建源图大小一样的全零矩阵
Mat t3 = Mat::zeros(src.size(), src.type());
imshow("t3", t3);
waitKey(0);
destroyAllWindows();
return 0;
}
创建源图大小一样的全零矩阵
Mat t3 = Mat::zeros(src.size(), src.type());
imshow("t3", t3);
4 遍历访问每个像素值
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/cats.jpg", IMREAD_COLOR); // IMREAD_COLOR:加载为3通道彩色图像
if (src.empty()) {
printf("image is empty!!!");
return -1;
}
// visit each pixel
int height = src.rows;
int width = src.cols;
int ch = src.channels();
for (int row = 0; row < height; row++) {
for (int col = 0; col < width;col++) {
if (ch == 3) {
Vec3b pixel = src.at<Vec3b>(row, col);
int blue = pixel[0];
int green = pixel[1];
int red = pixel[2];
src.at<Vec3b>(row, col)[0] = 255 - blue;
src.at<Vec3b>(row, col)[1] = 255 - green;
src.at<Vec3b>(row, col)[2] = 255 - red;
}
if (ch == 1) {
int pv = src.at<uchar>(row, col);
src.at<uchar>(row, col) = (255 - pv);
}
}
}
imshow("src", src);
waitKey(0);
destroyAllWindows();
return 0;
}

指针操作(实际工程中,多用指针,因为更加高效)
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main(int argc, char** argv) {
Mat src = imread("E:/cats.jpg", IMREAD_COLOR); // IMREAD_COLOR:加载为3通道彩色图像
if (src.empty()) {
printf("image is empty!!!");
return -1;
}
// visit each pixel
int height = src.rows;
int width = src.cols;
int ch = src.channels();
Mat result = Mat::zeros(src.size(), src.type());
for (int row = 0; row < height; row++) {
uchar* curr_row = src.ptr<uchar>(row);
uchar* result_row = result.ptr<uchar>(row);
for (int col = 0; col < width;col++) {
if (ch == 3) {
int blue = *curr_row++;
int green = *curr_row++;
int red = *curr_row++;
*result_row++ = blue;
*result_row++ = green;
*result_row++ = red;
}
if (ch == 1) {
int pv = *curr_row++;
*result_row++ = pv;
}
}
}
imshow("result", result);
waitKey(0);
destroyAllWindows();
return 0;
}

版权声明:本文为qq_41375318原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。