• 图像的卷积(滤波)运算(一)——图像梯度


    1. 卷积/滤波原理

    首先要明确的一点是图像的卷积/滤波运算,是针对原图像每一个像素进行处理,得到一个新的图像的过程。那么进行怎么样的运算呢?要知道图像能够被人所识别,是因为图像中每个像素并不完全是离散而独立的,每个像素都跟周围的像素相关。因此,对每一个像素,选定其周围一定范围内的像素值进行运算,得到新的图像的像素值也一定是相关的。而这个范围,就是卷积/滤波的窗口。

    只有相关的像素值是不够的,还需要改变因子——也就是我们说的卷积核了。它就是之前说的卷积/滤波的窗口大小,通常由数学原理推导出来的。

    最后,将窗口内覆盖的像素值和卷积核值相乘并相加,就得到新的像素值填充到新的图像中。对每个像素值都这样做,就是卷积/滤波运算后新的图像了。

    2. 具体实例

    以X方向上的一维卷积/滤波为例,选取一个卷积核(-1,0,1),对于图像像素X,其卷积运算的结果Y=-1 × Xa + 0 × X + 1 × Xb,即总是X的后一个像素与前一个像素之差。示意图如下:.

    其具体实现代码:

    #include <iostream>
    #include <opencv2opencv.hpp>
    
    using namespace cv;
    using namespace std;
    
    int main()
    {
    	//从文件中读取成灰度图像
    	const char* imagename = "D:\Data\imgDemo\lena.jpg";
    	Mat img = imread(imagename, IMREAD_GRAYSCALE);
    	if (img.empty())
    	{
    		fprintf(stderr, "Can not load image %s
    ", imagename);
    		return -1;
    	}
    
    	//OpenCV函数进行一维卷积(梯度图)
    	Mat xKernel = (Mat_<double>(1, 3) << -1, 0, 1);			//卷积算子
    	Mat Ix;
    	filter2D(img, Ix, -1, xKernel);
    
    	//自建算法进行一维卷积(梯度图)
    	Mat Ixx;
    	Ixx.create(img.cols, img.rows, CV_8UC1);
    	double xk[3] = { -1, 0, 1 };			//卷积算子
    	for (int i = 0; i < img.rows; ++i)
    	{
    		for (int j = 0; j < img.cols; ++j)
    		{
    			//img.at<uchar>(i, j) = 255;
    			uchar b[3] = { 0 };
    			b[0] = (j == 0 ? 0 : img.at<uchar>(i, j - 1));
    			b[1] = img.at<uchar>(i, j);
    			b[2] = (j == img.cols - 1 ? 0 : img.at<uchar>(i, j + 1));
    
    			double value = xk[0] * b[0] + xk[1] * b[1] + xk[2] * b[2];
    			value = (std::min)(std::max(value, 0.0), 255.0);
    			Ixx.at<uchar>(i, j) = (uchar)value;
    		}
    	}
    
    	//比较两者的结果
    	Mat c;
    	compare(Ix, Ixx, c, CMP_EQ);
    
    	//显示图像
    	imshow("原始", img);
    	imshow("梯度图(CV)", Ix);
    	imshow("梯度图(MY)", Ixx);
    	imshow("比较结果", c);
    
    	waitKey();
    	return 0;
    }
    

    在这里分别通过OpenCV的filter2D和自己的算法实现了X方向上的一维卷积/滤波运算,显示了其结果图。最后还用compare函数比较两者的差异,纯白(像素值255)色表示两者无差异。其运行结果如下:

    3. 图像梯度图

    这里的卷积核(-1,0,1)其实是从图像的梯度推导出来的。如果把图像看作是函数f(x),那么其X方向上梯度也就是函数X方向上的变化率为:

    对所有的像素卷积运算都会除以2,对结果无关紧要,因此可以将其舍弃。最后就得到卷积核(-1,0,1)。
    除此之外,也可以在Y方向上进行卷积,得到Y方向上的卷积图,只不过卷积核需要转置。

    4. 参考资料

    1.图像梯度的基本原理
    2.图像梯度计算

  • 相关阅读:
    样式
    样式表的类别、选择器和优先级
    随记
    框架
    表单元素
    HTLM内容容器标签和常用标签
    HTML5的意义、改变以及全局属性
    11月21日html基础
    感想 目标和展望
    C++结构体实例和类实例的初始化
  • 原文地址:https://www.cnblogs.com/charlee44/p/10582216.html
Copyright © 2020-2023  润新知