(一)矩阵的掩模操作
掩模操作实现图像对比度调整
红色是中心像素,从上到下,从左到右对每个像素做同样的处理操作,得到最终结果就是对比度提高之后的输出图像Mat对象。
I(i,j)=5*I(i.j)-[I(i-1,j)+I(i+1,j)+I(i,j-1)+I(i,j+1)]
1.定义掩模:Mat kernel=(Mat_< char >(3,3)<<0,-1,0,-1,5,-1,0,-1,0);
2.filter2D(src,dst,src.depth(),kernel);其中src与dst是Mat类型变量、src.depth表示位图深度,有32、24、8等,若为-1默认为与src深度相等。
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace cv;
int main(int argc,char** argv)
{
Mat src, dst;
src = imread("D:/studytest/lena.jpg"); //读取一张图片
if (!src.data)
{
printf("could not load image...\n");
return -1;
}
namedWindow("input_image", CV_WINDOW_AUTOSIZE);
imshow("input_image", src); //显示一张图
//row行 col列
/*int cols = (src.cols-1)*src.channels();
int offsetx = src.channels();
int rows = src.rows;
dst = Mat::zeros(src.size(), src.type());
for (int row = 1; row < rows - 1; row++)
{
const uchar* previous = src.ptr<uchar>(row - 1); //指针previous指向src的row-1行
const uchar* current = src.ptr<uchar>(row); //指针current指向src的row行
const uchar* next = src.ptr<uchar>(row + 1); //指针next指向src的row+1行
uchar* output = dst.ptr<uchar>(row); //指针output指向dst的row行
for (int col = offsetx; col < cols; col++)
{
output[col] =saturate_cast<uchar>( 5 * current[col] - (current[col - offsetx] + current[col + offsetx] + previous[col] + next[col])); //saturate_cast将小于0的置为0,将大于255的置为255,其余为原值
}
}*/
//上面注释掉的代码块与下面的掩模操作一样
double t = getTickCount(); //开始时间
Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);//掩模
filter2D(src, dst, src.depth(), kernel);//filter2D(src, dst, -1, kernel); -1默认为和原图深度一样
double timeconsume = (getTickCount() - t) / getTickFrequency(); //时间消耗
printf("time consume %.2f", timeconsume);
namedWindow("contract image demo", CV_WINDOW_AUTOSIZE);
imshow("contract image demo", dst);
waitKey(0);
return 0;
}
显示结果如下图所示:
(二)自定义线性滤波
#include<opencv2/opencv.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main(int argc, char** argv)
{
Mat src;
src = imread("D:/studytest/lena.jpg");
if (src.empty())
{
printf("could not load image...\n");
return -1;
}
namedWindow("input image", CV_WINDOW_AUTOSIZE);
imshow("input image", src);
Mat Robx, Roby,Sobx,Soby,lap;
//Robert X方向
Mat kernel_rx = (Mat_<int>(2, 2) << 1, 0, 0, -1);
filter2D(src, Robx, -1, kernel_rx, Point(-1, -1), 0, 0);
imshow("robert_x image", Robx);
//Robert Y方向
Mat kernel_ry = (Mat_<int>(2, 2) << 0, 1, -1, 0);
filter2D(src, Roby, -1, kernel_ry, Point(-1, -1), 0, 0);
imshow("robert_y image", Roby);
//Sobel X方向
Mat kernel_sx = (Mat_<int>(3, 3) << -1, 0, 1, -2, 0, 2, -1, 0, 1);
filter2D(src, Sobx, -1, kernel_sx, Point(-1, -1), 0, 0);
imshow("Sobel_x image", Sobx);
//Sobel Y方向
Mat kernel_sy = (Mat_<int>(3, 3) << -1, -2, -1, 0, 0, 0, 1, 2, 1);
filter2D(src, Soby, -1, kernel_sy, Point(-1, -1), 0, 0);
imshow("Sobel_y image", Soby);
//拉普拉斯算子
Mat kernel_lap = (Mat_<int>(3, 3) << 0, -1, 0, -1, 4, -1, 0, -1, 0);
filter2D(src, lap, -1, kernel_lap, Point(-1, -1), 0, 0);
imshow("lap image", lap);
//自定义卷积核来实现模糊
int c = 0;
int index = 0;
int ksize = 0;
Mat dst;
while (true)
{
c=waitKey(500);
if ((char)c == 27)//键盘上对应ESC
break;
ksize = 4+(index%5)*2+1;
Mat kernel = Mat::ones(Size(ksize, ksize), CV_32F)/(float)(ksize*ksize);
filter2D(src, dst, -1, kernel, Point(-1, -1));
index++;
imshow("output image", dst);
}
return 0;
}