OpenCV-C++ 图像掩模计算
利用一个掩模处理图像;
0 -1 0
-1 5 -1
0 -1 0
理解Mat矩阵存储格式
使用opencv读入一张图片,得到是一个表示BGR三个通道的矩阵,那么在内存空间中是怎么存储的呢?
如下图所示,Row 0, Row 1,..., Row n 表示图像的每一行,与图像高度相关;
Column 0, Column 1,..., Column m 表示图像的每一列, 与图像宽度相关;
但是实际在存储的时候,是先连续存储每一个像素的B, G, R三个值,在存储下一个像素;
同时,由于是一个多维数组,必定有一个头指针,指向第一行;对指针加1,用来放来第二行;
这样获取到每一行的指针后,再访问其第几列;
C++实现
#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace std;
using namespace cv;
int main(){
// 读入图片
Mat img = imread("/home/chen/dataset/lena.jpg");
// 显示图片
namedWindow("lena", WINDOW_AUTOSIZE);
imshow("lean", img);
waitKey(0);
// 执行掩模计算
int cols = img.cols * img.channels(); // 获取每一行所代表的一维数组有多少元素
int offset = img.channels();
int rows = img.rows;
Mat dst = Mat::zeros(img.size(), img.type()); // 掩模计算后的输出图像
for (int row = 1; row < (rows - 1); row++){
const uchar* previous = img.ptr<uchar>(row - 1); // 获取上一行的指针, 是一个指向常量的指针,不能修改指向对象的值
const uchar* current = img.ptr<uchar>(row); // 获取当前行的指针
const uchar* next = img.ptr<uchar>(row + 1); // 获取下一行的指针
uchar* output = dst.ptr<uchar>(row); // 获取目标图像当前行的指针
for (int col = offset; col < (cols - 1); col++){
// 核心掩模计算
output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offset] + current[col+offset] + previous[col] + next[col]));
}
}
namedWindow("img after mask.\n", WINDOW_AUTOSIZE);
imshow("img after mask", dst);
waitKey(0);
return 0;
}
需要注意的是,从img.ptr<uchar>(0)
获取的是第0行的指针; uchar代表的元素类型
API调用
#include <iostream>
#include <opencv2/opencv.hpp>
#include <math.h>
using namespace std;
using namespace cv;
int main(){
// 读入图片
Mat img = imread("/home/chen/dataset/lena.jpg");
// 显示图片
namedWindow("lena", WINDOW_AUTOSIZE);
imshow("lean", img);
printf("col: %d, rows: %d, channels: %d, depth: %d\n", img.cols, img.rows, img.channels(), img.depth());
printf("dims: %d, type: %d\n" , img.dims, img.type());
waitKey(0);
// 利用API执行掩模计算
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
Mat dst2;
filter2D(img, dst2, img.depth(), kernel); // 使用API执行掩模计算
namedWindow("img after mask-api", WINDOW_AUTOSIZE);
imshow("img after mask-api", dst2);
waitKey(0);
return 0;
}