OpenCV--矩阵的掩膜操作

所谓掩膜其实就是一个矩阵,然后根据这个矩阵重新计算图片中像素的值。
掩膜主要有以下用途:

  • 提取感兴趣区,用预先制作的感兴趣区掩模与待处理图像相乘,得到感兴趣区图像,感兴趣区内图像值保持不变,而区外图像值都为0。
  • 屏蔽作用,用掩模对图像上某些区域作屏蔽,使其不参加处理或不参加处理参数的计算,或仅对屏蔽区作处理或统计。
  • 结构特征提取,用相似性变量或图像匹配方法检测和提取图像中与掩模相似的结构特征。
  • 特殊形状图像的制作。

掩膜操作实现图像对比度的提高:

图像像素指针的获取:
Mat.ptr<uchar>(row):获取第row行的图像像素指针。图像的行数从0开始计数

获取点P(row,col)的像素值:P(row.col)= Mat.ptr<uchar>(row)[col]

图片全被服务器整没了。。。

使用的掩膜:
这里写图片描述

红色是中心元素I(i,j)。掩膜操作公式:
I ( i , j ) = 5 ∗ I ( i , j ) − [ I ( i − 1 , j ) + I ( i + 1 , j ) + I ( i , j − 1 ) + I ( i , j + 1 ) ] I(i,j) = 5*I(i,j)-[I(i-1,j)+I(i+1,j)+I(i,j-1)+I(i,j+1)] I(i,j)=5I(i,j)[I(i1,j)+I(i+1,j)+I(i,j1)+I(i,j+1)]
用此掩膜从上至下,从左至右对图像进行操作,得到的图像就是增强对比度的图像。

实例代码:

void KernelOper(){
	Mat src,dest;
	src = imread("girl.jpg");
	if(!src.data){
		cout << "文件打开失败" << endl;
		return ;
	}
	namedWindow("掩膜操作前",WINDOW_AUTOSIZE);
	imshow("掩膜操作前",src);
	dest = Mat::zeros(src.size(),src.type());//生成一个和源图像大小相等类型相同的全0矩阵
	int cols = (src.cols-1)*src.channels();//获取图像的列数,一定不要忘记图像的通道数
	int rows = src.rows;//获取图像的行数
	int offsetx = src.channels();
	
	for (int row = 1; row < rows-1;row++){
		uchar* previous = src.ptr<uchar>(row-1);
		uchar* current = src.ptr<uchar>(row);
		uchar* next = src.ptr<uchar>(row+1);
		uchar* output = dest.ptr<uchar>(row);
		for (int col = offsetx; col < cols; col++){
			output[col] =  5*current[col] - (previous[col]+next[col]+current[col-1]+current[col+1]); 
		}
	}

	namedWindow("掩膜操作后",WINDOW_AUTOSIZE);
	imshow("掩膜操作后",dest);

	cvWaitKey();
}

这里写图片描述

我们可以看见掩膜操作后的图像对比度明显提高了,但是美中不足的是出现了一些不好的小斑点。这是因为这项像素点的值的范围不在0~255之间了。
解决方法:
使用函数saturate_cast(像素值)
这个函数的作用就是确保RGB的值在0~255之间。
saturate_cast(-100)返回0;
saturate_cast(100)返回100;
saturate_cast(280)返回255。
添加上:

output[col] = saturate_cast( 5*current[col] - (previous[col]+next[col]+current[col-1]+current[col+1])); 

这里写图片描述
完美!!

OpenCV使用函数filter2D来实现掩膜操作:

定义掩膜:
Mat kernel = (Mat<uchar>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
void KernelOper2(){
	Mat src,dest;
	src = imread("girl.jpg");
	if(!src.data){
		cout << "文件打开失败" << endl;
		return ;
	}
	namedWindow("掩膜操作前",CV_WINDOW_AUTOSIZE);
	imshow("掩膜操作前",src);
	
	Mat kernel = (Mat_<char>(3,3)<<0,-1,0,-1,5,-1,0,-1,0);//定义掩膜
	//调用filter2D
	filter2D(src,dest,src.depth(),kernel);

	namedWindow("掩膜操作后",CV_WINDOW_AUTOSIZE);
	imshow("掩膜操作后",dest);
	cvWaitKey();
}

这里写图片描述

你可能感兴趣的:(数字图像处理)