高斯和拉普拉斯金字塔(Gaussian and Laplacian Pyramids)

通常,我们使用的是恒定尺寸的图像。但在某些情况下,我们需要用不同的分辨率来处理(相同的)图像。例如,当在图像中搜索某物时,例如面部,我们不确定对象在图像中会出现多大的大小。在这种情况下,我们需要创建一组具有不同分辨率的相同图像,并在它们中搜索对象。这些具有不同分辨率的图像被称为图像金字塔(因为当它们被保存在堆栈中,在底部具有最高分辨率的图像和顶部的最低分辨率图像时,它看起来像金字塔)。

图像金字塔有两种:高斯金字塔和 Laplacian 金字塔;

一幅图像的金字塔,是以一系列以金字塔形状排列的分辨率初步降低的图像的集合。如下图所示:

金字塔

  1. 金字塔的底部是待处理图像的高分辨率的表示,而顶部是低分辨率的表示
  2. 当金子塔向上层移动的时候,尺寸和分辨率都会降低。
    其实,在构造上述金字塔的过程中,遵循了如下的流程:
    流程
  3. 拿到第j级的图像后,先通过一个低通filter,这个filter可以选取我们前面学过的任何一个filter。比如理想低通,巴特沃斯,高斯低通。然后在进行以2为步长的下采样。
  4. 这个时候,步骤执行到了一个交汇点处,我们先忽略掉内插器和插入滤波那一部分,那么直接将刚刚第一步得到的结果输出,就得到了j-1级的近似图像。
  5. 然后通过第一步和第二步不停的迭代,直到最终输出0级的图像就结束。这个时候,把所有得到的近似图像按照尺寸从大到小进行堆叠,就得到了前面讲的图像金字塔。
    其实,高斯金字塔的构造过程就是上述的这个过程,只不过在一开始进行滤波的时候,我们只能选择用高斯低通滤波器进行滤波。高斯低通滤波器表达式如下:
    高斯

最后,在图像处理和计算机视觉中,高斯核函数的五个重要性质,这些性质使得它在早期图像处理中特别有用.这些性质表明,高斯平滑滤波器无论在空间域还是在频率域都是十分有效的低通滤波器,:
二维高斯函数具有旋转对称性,即滤波器在各个方向上的平滑程度是相同的.
高斯函数是单值函数。这表明,高斯滤波器用像素邻域的加权均值来代替该点的像素值,而每一邻域像素点权值是随该点与中心点的距离单调增减的。
高斯函数的傅里叶变换频谱是单瓣的。图像常被不希望的高频信号所污染(噪声和细纹理)。
高斯滤波器宽度(决定着平滑程度)是由参数σ表征的,而且σ和平滑程度的关系是非常简单的.σ越大,高斯滤波器的频带就越宽,平滑程度就越好。
由于高斯函数的可分离性,大高斯滤波器可以得以有效地实现。二维高斯函数卷积可以分两步来进行,首先将图像与一维高斯函数进行卷积,然后将卷积结果与方向垂直的相同一维高斯函数卷积.因此,二维高斯滤波的计算量随滤波模板宽度成线性增长而不是成平方增长。
讲完高斯金字塔,我们再回到这张图:
如果此刻考虑到内插器和插入滤波器的部分,那么此时通过将经过高斯低通滤波器和下采样后的图片经过这两个组件。其实,就是在对这组图像进行近似重建,因为这个过程的所有操作刚刚好和上一个过程(高斯低通滤波器+下采样)是逆过来。
那么通过将重建后的图像和原始的第j级的输入图像进行相减,就得到了j级的预测残差,此时得到的就是拉普拉斯金字塔了。拉普拉斯金字塔的作用是重建高斯金字塔。预测残差如下:
拉普拉斯

We can find Gaussian pyramids using cv.pyrDown() and cv.pyrUp() functions.

Below is the 4 levels in an image pyramid.

高斯金字塔

拉普拉斯金字塔是由高斯金字塔形成的,没有专门的功能。拉普拉斯金字塔图像就像边缘图像一样。它的大多数元素都是零。它们被用于图像压缩。拉普拉斯金字塔中的水平是由高斯金字塔中的水平和高斯金字塔中的上层的扩展版本之间的差异形成的。拉普拉斯水平的三个层次看起来如下(对比度调整以增强内容):
拉普拉斯金字塔

基于金字塔的图像融合

金字塔的一个应用是图像融合。例如,在图像拼接中,您需要将两个图像叠加在一起,但由于图像之间的不连续性,它可能看起来不太好。在这种情况下,与金字塔的图像混合可以使您无缝混合,而不会在图像中留下大量数据。其中一个经典例子是两种水果,橙子和苹果的混合。看看现在的结果来理解我在说什么:

李果

代码一:

void buildGaussianPyramid() {//金字塔内容为每一层的掩模
    assert(leftLapPyr.size()>0);

    maskGaussianPyramid.clear();
    Mat currentImg;
    //store color img of blend mask into maskGaussianPyramid
    cvtColor(blendMask, currentImg, CV_GRAY2BGR);
    maskGaussianPyramid.push_back(currentImg); //0-level

    currentImg = blendMask;
    for (int l=1; l<levels+1; l++) {
        Mat _down;
        if (leftLapPyr.size() > l)
            pyrDown(currentImg, _down, leftLapPyr[l].size());
        else
            pyrDown(currentImg, _down, leftHighestLevel.size()); //lowest level

        Mat down;
        cvtColor(_down, down, CV_GRAY2BGR);
        maskGaussianPyramid.push_back(down);//add color blend mask into mask Pyramid
        currentImg = _down;
    }
}

代码二:

void buildLaplacianPyramid(const Mat& img, vector<Mat_<Vec3f> >& lapPyr, Mat& HighestLevel) {
    lapPyr.clear();
    Mat currentImg = img;
    for (int l=0; l<levels; l++) {
        Mat down,up;
        pyrDown(currentImg, down);
        pyrUp(down, up,currentImg.size());
        Mat lap = currentImg - up;
        lapPyr.push_back(lap);
        currentImg = down;
    }
    currentImg.copyTo(HighestLevel);
}

代码三:

// 变量定义

#include "opencv2/opencv.hpp"
using namespace cv;

Mat_<Vec3f> left;
Mat_<Vec3f> right;
Mat_<float> blendMask;

vector<Mat_<Vec3f> > leftLapPyr,rightLapPyr,resultLapPyr;//Laplacian Pyramids
Mat leftHighestLevel, rightHighestLevel, resultHighestLevel;
vector<Mat_<Vec3f> > maskGaussianPyramid; 
int levels;

参考文章:

https://docs.opencv.org/master/dc/dff/tutorial_py_pyramids.html

https://zhuanlan.zhihu.com/p/32815143

https://www.cs.utah.edu/~arul/report/node12.html

猜你喜欢

转载自blog.csdn.net/wangbaodong070411209/article/details/80055095