所谓掩膜其实就是一个矩阵,然后根据这个矩阵重新计算图片中像素的值。
掩膜主要有以下用途:
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)=5∗I(i,j)−[I(i−1,j)+I(i+1,j)+I(i,j−1)+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]));
完美!!
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();
}