一、掩码操作
矩阵的掩码操作很简单。其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响。从数学观点看,我们用自己设置的权值,对像素邻域内的值做了个加权平均。
二、操作实践
2.1 基于像素邻域的掩码操作
/*!
* \brief myMaskFun
* \param srcImage
* \return
*/
Mat myMaskFun(Mat srcImage)
{
const int nChannels = srcImage.channels();
Mat resultImage(srcImage.size(), srcImage.type());
for (int j = 1; j < srcImage.rows - 1; j++)
{
const uchar* previous = srcImage.ptr<uchar>(j - 1);
const uchar* current = srcImage.ptr<uchar>(j);
const uchar* next = srcImage.ptr<uchar>(j + 1);
uchar * output = resultImage.ptr<uchar>(j);
for (int i = nChannels; i < nChannels*(srcImage.cols - 1); ++i)
{
*output++ = saturate_cast<uchar>(current[i - nChannels] + current[i + nChannels]
+ previous[i] + next[i]) / 4;
}
}
//! 进行边界处理
resultImage.row(0).setTo(Scalar(0));
resultImage.row(resultImage.rows - 1).setTo(Scalar(0));
resultImage.col(0).setTo(Scalar(0));
resultImage.col(resultImage.cols - 1).setTo(Scalar(0));
return resultImage;
}
2.2 系统函数方式
/*!
* \brief systemMaskFun
* \param srcImage
* \return
*/
Mat systemMaskFun(Mat srcImage)
{
Mat resultImage(srcImage.size(), srcImage.type());
//! 构造核函数因子
Mat kern = (Mat_<float>(3, 3) << 0, 1, 0,
1, 0, 1,
0, 1, 0) / (float)(4);
filter2D(srcImage, resultImage, srcImage.depth(), kern);
return resultImage;
}
filter2D函数详见附录1。
代码详见《OpenCV掩码操作练习》
参考资料:
附录1:filter2D函数
在OpenCV中提供了filter2D函数用来专门应用于计算图像卷积的操作,首先简单介绍一下这个函数:
void filter2D( InputArray src, OutputArray dst, int ddepth,InputArray kernel,Point anchor=Point(-1,-1),double delta=0, int borderType=BORDER_DEFAULT );
这个函数基本上是用来实现图像的卷积操作,前两个参数分别表示输入图像和输出图像,第三个参数ddepth表示的是图像的深度,如果这个值设置为负数,则这个图像的深度与输入的源图像的深度相同,否则就需要根据源图像的深度进行相关的设置
例如,若src.depth()=CV_8U,则ddepth=-1 / CV_16S / CV_32F / CV_64F,若src.depth() = CV_16U/CV_16S,则ddepth = -1 / CV_32F / CV_64F,若src.depth() =CV_32F,则ddepth= -1 / CV_32F / CV_64F,若src.depth() = CV_64F,则ddepth = -1 / CV_64F.
第四个参数kernel是卷积核算子,为单通道浮点矩阵,如果对多通道应用不同的卷子核算子计算,需要首先分离成为单通道后在进行单通道上的操作。参数anchor是卷积核锚点,默认值是(-1,-1)表示的是卷积核中心。参数delta是平滑系数,目标图像生成前可已通过设定这个值用于目标图像的平滑操作。最后一个参数表示的是边界类型,有默认值BORDER_DEFAULT)
需要说明的是,这个函数常常应用于线性滤波技术中,当使用卷积核算子计算的图像目标点在图像外部时,需要对指定边界进行插值运算。这个函数实际上计算的是图像的相关性,而非卷积操作,它的计算公式如下:
其中0<= x' < kernel.cols,0<= y' < kernel.rows
附录 2:颜色空间转换cvtColor()
void cvtColor(InputArray src, OutputArray dst, int code, int dstCn=0 );
参数解释:
. InputArray src: 输入图像即要进行颜色空间变换的原图像,可以是Mat类
. OutputArray dst: 输出图像即进行颜色空间变换后存储图像,也可以Mat类
. int code: 转换的代码或标识,即在此确定将什么制式的图片转换成什么制式的图片,后面会详细将
. int dstCn = 0: 目标图像通道数,如果取值为0,则由src和code决定