OpenCV学习笔记之掩码操作

一、掩码操作

         矩阵的掩码操作很简单。其思想是:根据掩码矩阵(也称作核)重新计算图像中每个像素的值。掩码矩阵中的值表示近邻像素值(包括该像素自身的值)对新像素值有多大影响。从数学观点看,我们用自己设置的权值,对像素邻域内的值做了个加权平均。

二、操作实践

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决定 

猜你喜欢

转载自blog.csdn.net/a8039974/article/details/104861383