前言
矩阵的掩码或者卷积操作非常简单。其思想是,我们根据掩码矩阵(也称为核)重新计算图像中每个像素的值。此掩码保存的值将调整相邻像素(和当前像素)对新像素值的影响程度。从数学的观点来看,我们用指定的值进行加权平均。
例如我们对图像做对比度增强方法。每个像素应用下面的公式:
也可以使用卷积核表示:通过将掩码矩阵的中心放在要计算的像素上并将像素值与重叠矩阵值相乘来使用掩码。和公式表示方法是相同的操作效果,但是在大型矩阵的情况下,后一种表示法更容易查看。
一、像素访问方式
代码示例:
cv::Mat src;
src = cv::imread("D:\\QtProject\\Opencv_Example\\MaskOperate\\MaskOperate.png", cv::IMREAD_COLOR);
if (src.empty()) {
cout << "Cannot load image" << endl;
return;
}
CV_Assert(src.depth() == CV_8U);
cv::Mat Result = src.clone();
const int nChannels = src.channels();
for(int j = 1 ; j < src.rows-1; ++j)
{
const uchar* previous = src.ptr<uchar>(j - 1);
const uchar* current = src.ptr<uchar>(j );
const uchar* next = src.ptr<uchar>(j + 1);
uchar* output = Result.ptr<uchar>(j);
for(int i= nChannels;i < nChannels*(src.cols-1); ++i)
{
*output++ = cv::saturate_cast<uchar>(5*current[i]
-current[i-nChannels] - current[i+nChannels] - previous[i] - next[i]);
}
}
Result.row(0).setTo(cv::Scalar(0));
Result.row(Result.rows-1).setTo(cv::Scalar(0));
Result.col(0).setTo(cv::Scalar(0));
Result.col(Result.cols-1).setTo(cv::Scalar(0));
运行效果:
二、filter2D 函数
函数原型:
CV_EXPORTS_W void filter2D( InputArray src, OutputArray dst, int ddepth,
InputArray kernel, Point anchor = Point(-1,-1),
double delta = 0, int borderType = BORDER_DEFAULT );
参数说明:
src:输入图像。
dst输出与src相同大小和相同通道数的图像。
ddepth:目标图像的期望深度,参见@ref filter_depth " combined "
kernel:卷积核,一个单通道浮点矩阵;如果你想应用不同的内核到不同的通道,使用split分割图像到单独的彩色平面并单独处理他们。
anchor:所述内核的锚定,该锚定指示滤过的点在内核中的相对位置;锚应该位于内核中;默认值(-1,-1)表示锚位于内核中心。
delta:添加到dst输出图像的偏移量。
borderType:像素边界模式,参见#BorderTypes
代码示例:
cv::Mat src;
src = cv::imread("D:\\QtProject\\Opencv_Example\\MaskOperate\\MaskOperate.png", cv::IMREAD_COLOR);
if (src.empty()) {
cout << "Cannot load image" << endl;
return;
}
cv::Mat Result1;
cv::Mat kernel = (cv::Mat_<char>(3,3) << 0, -1, 0,
-1, 5, -1,
0, -1, 0);
cv::filter2D( src, Result1, src.depth(), kernel);
show(Result1);
运行效果: