1、什么是掩膜操作?

  • 掩膜操作是一种使用特定物品对某一区域进行掩盖,从而能够对指定区域进行特殊处理的一种操作方式。

2、掩膜操作的作用

  • 在进行图像处理中,通过掩膜操作能够提升图像整体的对比度,使得图片更加醒目。
  • 第一幅是没有经过掩膜操作的图片:
  • 第二幅是经过掩膜操作的图片

由上述两幅图片对比可以发现,第二幅图片纹理更加清晰,对比度更加明显。

3、对OpenCV中掩膜操作算法的理解

(1)掩膜操作的公式:

OpenCV 按掩膜填充颜色_OpenCV 按掩膜填充颜色

这个公式所表述的意思其实就是将某个像素值重置,重置之后的值与和该像素相邻的上下左右四个像素值有关,具体的数学关系就是:该点经过掩膜之后像素值 = 五倍的该点原先的像素值 - 与之相邻上面的像素值 - 与之相邻下面的像素值 - 与之相邻左边的像素值 - 与之相邻右边的像素值。

(2)下面通过图像再次讲解:

OpenCV 按掩膜填充颜色_掩膜操作_02

其中a表示我们要处理的像素点,b、c、d、e分别为与a相邻的上下左右的像素点。

未经过掩膜处理之前,a点的像素值为a,经过掩膜操作处理之后,a点的像素值为A,则

OpenCV 按掩膜填充颜色_像素点_03

上述3*3表格如果用数字表示,则对应的矩阵应当是:[ 0 -1 0; -1 5 -1; 0 -1 0]

(3)一副图片在计算机中是通过一个庞大的数字矩阵存储。因此,这个3*3的表格就相当于一个掩膜矩阵,通过这个掩膜矩阵,就可以对图片矩阵进行掩膜操作(改变图片矩阵的像素值)。但是,这个掩膜矩阵在图片矩阵中到底是怎样运动的呢?它会改变那些数字?会用到哪些数字呢?

OpenCV 按掩膜填充颜色_重置_04

如上图所示,有一个n*m的数字矩阵,掩膜矩阵会改变从第二行到第(n-1)行、第二列到第(m-1)列的像素值,也就是上述中红线区域之内的像素值,靠近矩阵边缘的一行(列)像素值并不会改变。

(4)通道数直接决定图片数字矩阵的列数,影响着后面代码的编写。对于单通道而言,n*m的数字矩阵的列数就是m;但是对于三通道(RGB图片)而言,n*m的数字矩阵的列数就是m*3。这是因为,在三通道矩阵中,每一列中又有三个子列。掩膜矩阵在进行上述的移动是,起始行不便,但是起始列应当从第一列(第三个子列)开始进行移动。

(5) 进行代码编写:

//根据掩膜公式,进行算法编程
	Mat dst;		//另创建一个Mat对象,用来存储进行掩膜操作之后的图片
	dst = Mat::zeros(src.size(), src.type());		//初始化dst对象

	//获取原图片的行数以及列数
	int src_rows = src.rows;
	int src_cols = (src.cols - 1) * src.channels();
	int offsetx = src.channels();

	//通过指针过去图像的像素并进行掩膜操作
	for (int row = 1; row < src_rows - 1; row++) {		//从第二行到倒数第二行
		const uchar * previous = src.ptr<uchar>(row - 1);	//指针指向上一行
		const uchar * current = src.ptr<uchar>(row);		//指针指向本行
		const uchar * next = src.ptr<uchar>(row + 1);		//指针指向下一行
		uchar * output = dst.ptr<uchar>(row);	//用来保存经过掩膜操作之后的像素
		for (int col = offsetx; col < src_cols; col++) {		//从第二列到倒数第二列RGB图像每一列又分为三小列
			output[col] = saturate_cast<uchar>(5 * current[col] - (current[col - offsetx] + current[col + offsetx] 
				+ previous[col] + next[col]));	//确保像素值在0~255之间
		}
	}

4、相关API

Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
	filter2D(src, dst, -1, kernel);