• 图像的掩膜操作



    注:原创不易,转载请务必注明原作者和出处,感谢支持!

    所涉及的API

    void cv::filter2D(
    	InputArray src,						// 输入图像
        OutputArray dst,					// 输出图像
        int ddepth,							// 输出图像深度
        InputArray kernel,					// 掩膜矩阵(核)
        Point anchor = Point(-1, -1),
        double delta = 0,
        int borderType = BORDER_DEFAULT
    );
    

    图像的掩膜操作

    什么是图像的掩膜操作?

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

    比如,下面这个公式表示用5倍当前像素的值减去该像素上、下、左、右四个像素值和,得到的结果赋值给当前像素。使用该公式可以用于提升图像的对比度。调节(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)] ]

    上面的公式可以用掩膜矩阵表示成如下的形式。

    [egin{bmatrix} 0&-1&0\ -1&5&-1\ 0&-1&0 end{bmatrix} ]

    如果不使用OpenCV提供的API,直接利用OpenCV提供的对图像像素的访问功能,则上述公式所对应的掩膜操作可以用下面的代码实现。

    #include <iostream>
    #include <opencv2/opencv.hpp>
    
    using namespace cv;
    using namespace std;
    
    int main(int argc, char **argv)
    {
    	// load image and show
    	Mat src = imread("D:\IMG\lena.jpg", IMREAD_COLOR);
    	if (!src.data)
    	{
    		cout << "Error : could not load image." << endl;
    		return -1;
    	}
    	imshow("input image", src);
    
    	// image sharpen
    	auto rows = src.rows;
    	auto cols = src.cols;
    	auto channels = src.channels();
    	Mat dst = Mat::zeros(src.size(), src.type());
    
    	decltype(src.rows) row, col;
    	for (row = 1; row < (rows - 1); ++row)
    	{
    		// get points pointed to rows of the source image
    		const uchar *prev = src.ptr<uchar>(row - 1);
    		const uchar *curr = src.ptr<uchar>(row);
    		const uchar *next = src.ptr<uchar>(row + 1);
    		uchar *output = dst.ptr<uchar>(row);
    
    		for (col = channels; col < ((cols - 1) * channels); ++col)
    		{
    			output[col] = saturate_cast<uchar>(7 * curr[col] - curr[col - channels]
    				- curr[col + channels] - prev[col] - next[col]);
    		}
    	}
    	imshow("sharpen image", dst);
    
    	waitKey(0);
    	return 0;
    }
    

    如果使用filter2D()则可以将上述公式作如下的实现。

    // by filter2D()
    Mat kernel = (Mat_<char>(3, 3) << 0, -1, 0, -1, 9, -1, 0, -1, 0);
    filter2D(src, dst, src.depth(), kernel);
    

    对于上述两种实现方式,有一些需要注意的地方:
    (1) 在不使用API直接手写实现方式中,图像最外边的一圈像素将会是黑色的。因为核的大小是3x3的,无法对图像的最边缘一圈像素进行掩膜计算。
    (2) 使用APIfilter2D()通常的性能会比自己手写更好。因为OpenCV针对API的性能进行了很好的优化。

    实现效果

    • 原图

    • 直接手写实现,I(i,j)的权重分别为5, 7, 9

    • 使用filter2D实现,I(i,j)的权重分别为5, 7, 9


  • 相关阅读:
    Ubuntu系统下《汇编语言》环境配置

    GetDiskFreeSpaceEx的使用
    夏走了
    小笨妞
    项目管理怎么可以这样子!


    浪费
    查找文件夹
  • 原文地址:https://www.cnblogs.com/laizhenghong2012/p/11251593.html
Copyright © 2020-2023  润新知