当前位置: 欣欣网 > 码农

OpenCV筑基之图像金字塔

2024-03-29码农

1. 尺度空间和图像金字塔

尺度空间 是图像在不同尺度下的连续表示。其中最常见的是使用高斯核对图像进行卷积。高斯滤波可以平滑图像,从而消除图像中的细微细节。随着高斯滤波核尺度的增加,图像变得越来越平滑,直到只剩下最基本的特征。

图像金字塔 是尺度空间的一种具体实现方式。它是由一系列不同分辨率的图像组成,这些图像以金字塔的形状排列如下图所示。

图像金字塔.png

常见的图像金字塔有以下几种:

  • 高斯金字塔 (Gaussian Pyramid):高斯金字塔是通过对图像进行高斯滤波和下采样来构建的。高斯滤波可以平滑图像,下采样可以降低图像的分辨率。高斯金字塔具有尺度不变性,可以用于尺度不变的图像处理任务。

  • DoG 金字塔 (Difference of Gaussians Pyramid):DoG 金字塔是通过对高斯金字塔 相邻层 进行 差分 来构建的。DoG 金字塔可以捕捉图像的局部特征,可以用于目标检测和边缘检测等任务。

  • 拉普拉斯金字塔 (Laplacian Pyramid):拉普拉斯金字塔是通过对高斯金字塔进行 差分 来构建的。拉普拉斯金字塔可以捕捉图像的边缘和细节信息,可以用于图像融合和特征提取等任务。

  • SIFT 金字塔 (Scale-Invariant Feature Transform Pyramid):SIFT 金字塔是通过对图像进行高斯滤波和 DoG 滤波来构建的。SIFT 金字塔具有尺度不变性和旋转不变性,可以用于图像匹配和目标识别等任务。

  • 图像金字塔通常通过对图像进行 下采样 上采样 来构建。下采样可以降低图像的分辨率,上采样可以提高图像的分辨率。

    尺度空间和图像金字塔在计算机视觉和图像处理领域有着广泛的应用。尺度空间可以用于尺度不变的图像处理任务,例如图像匹配和目标检测。图像金字塔可以用于图像融合、图像配准和特征提取等任务。

    2. 高斯金字塔

    高斯金字塔 通过对图像进行高斯滤波和下采样获得一系列下采样图像。高斯金字塔的 下采样 是对高斯滤波后的图像进行,以降低图像的分辨率。下采样可以通过以下几种方式实现:

  • 平均池化 :对图像的每个局部区域进行平均操作,从而得到一个像素值。

  • 最大池化 :对图像的每个局部区域进行最大值操作,从而得到一个像素值。

  • 双线性插值 :通过对相邻像素进行插值来得到新的像素值。

  • 高斯金字塔的构建过程如下:

  • 将原图作为高斯金字塔的第 0 层图像

  • 对高斯金字塔的第 i 层(i = 0,1,2...)图像进行高斯滤波

  • 对高斯滤波后的图像进行亚采样,生成高斯金字塔的第 i+1 层图像

  • 高斯金字塔的第 i 层图像的尺寸为:

    其中, 和 是原始图像的宽度和高度。

  • 重复前面两步,直到达到预定的金字塔层数。

  • 下面的代码展示了上述步骤,通过 GaussianBlur() 实现高斯滤波,通过双线性插值实现下采样,最终完成构建高斯金字塔。

    #include<opencv2/core.hpp>
    #include<opencv2/imgproc.hpp>
    #include<opencv2/opencv.hpp>
    usingnamespacestd;
    usingnamespace cv;
    // 构建高斯金字塔
    voidbuildGaussianPyramid(Mat& image, vector<Mat>& pyramid, int levels){
    Mat temp = image.clone();
    pyramid.push_back(temp);
    for (int i = 1; i < levels; i++) {
    // 高斯滤波
    Mat blurred;
    GaussianBlur(temp, blurred, Size(55), 0);
    Mat downSampled(blurred.rows / 2, blurred.cols / 2, blurred.type());
    resize(blurred, downSampled, downSampled.size(), 00, INTER_LINEAR);
    pyramid.push_back(downSampled);
    temp = downSampled;
    }
    }
    intmain(){
    Mat src = imread(".../lotus.jpg");
    int numLevels = 4;
    vector<Mat> pyramid;
    buildGaussianPyramid2(src,pyramid,numLevels);
    for (int i = 0; i < numLevels; i++) {
    imshow("Gaussian Pyramid Level " + to_string(i), pyramid[i]);
    }
    waitKey(0);
    return0;
    }






    构建高斯金字塔.png

    OpenCV 提供了 pyrDown() 函数来构建高斯金字塔,该函数先对图像进行高斯滤波然后对图像进行下采样。

    #include<opencv2/core.hpp>
    #include<opencv2/imgproc.hpp>
    #include<opencv2/opencv.hpp>
    usingnamespacestd;
    usingnamespace cv;
    // 构建高斯金字塔
    voidbuildGaussianPyramid2(Mat& image, vector<Mat>& pyramid, int levels){
    Mat temp = image.clone();
    pyramid.push_back(temp);
    for (int i = 1; i < levels; i++) {
    Mat downSampled;
    pyrDown(temp, downSampled);
    pyramid.push_back(downSampled);
    temp = downSampled;
    }
    }
    intmain(){
    Mat src = imread(".../lotus.jpg");
    int numLevels = 4;
    vector<Mat> pyramid;
    buildGaussianPyramid2(src,pyramid,numLevels);
    for (int i = 0; i < numLevels; i++) {
    imshow("Gaussian Pyramid Level " + to_string(i), pyramid[i]);
    }
    waitKey(0);
    return0;
    }





    3. DoG 金字塔

    在该系列的第十一篇文章中,曾经介绍过 DoG 算子。

    DoG 金字塔 (Difference of Gaussians Pyramid)是指通过对相邻尺度的高斯金字塔进行差分来构建的图像金字塔。DoG 金字塔可以捕捉图像的局部特征,例如边缘和角点,可以用于目标检测和边缘检测等任务。

    DoG 金字塔的构建过程如下:

    1. 对原始图像进行高斯滤波,得到不同尺度的高斯金字塔。

    2. 对相邻尺度的高斯金字塔进行差分,得到 DoG 金字塔。

    DoG 金字塔的第 i 层可以表示为:

    DoG(i) = G(i) - G(i-1)

    1. 确定极值点,对 DoG 金字塔进行极值点检测,找到图像的局部特征点。

    DoG 金字塔的应用:

  • 目标检测:它可以捕捉图像的局部特征,例如边缘和角点。

  • 边缘检测:它可以捕捉图像的边缘信息。

  • 4. 拉普拉斯金字塔

    拉普拉斯金字塔 它可以捕捉图像的边缘和细节信息,它也是基于高斯金字塔构建的,常用于图像融合和特征提取等任务。

    拉普拉斯金字塔的构建步骤如下:

    1. 构建高斯金字塔。

    2. 对高斯金字塔进行差分,得到拉普拉斯金字塔。拉普拉斯金字塔的第 i 层可以表示为:

    Laplacian(i) = G(i) - Expand(G(i+1))

    其中,G(i) 是高斯金字塔的第 i 层,Expand() 是图像的 上采样 操作。拉普拉斯金字塔捕捉了高斯金字塔连续层之间的细节差异,强调了原始图像中存在的边缘和高频分量。

    不同类型的图像金字塔比较:

    金字塔类型 特性 构建方式 应用
    高斯金字塔 提供图像的多尺度表示 高斯模糊和下采样 尺度不变性、图像压缩
    DoG 金字塔 比较高斯金字塔的相邻级别,强调模糊差异并捕获角点和斑点等局部特征。 高斯金字塔中相邻层的差异 目标检测、边缘检测
    拉普拉斯金字塔 关注不同尺度下图像中存在的所有边缘和细节。 通过获取高斯金字塔中相邻级别之间的差异来计算拉普拉斯金字塔,涉及对上一层的金字塔图像进行上采样。 图像融合、增强、纹理分析

    下面的代码展示了如何基于高斯金字塔构建拉普拉斯金字塔:对第 i+1 层图像通过双线性插值实现上采样,然后用第 i 层金字塔的图像 - 刚才上采样的图像,得到第 i 层拉普拉斯金字塔的图像。

    #include<opencv2/core.hpp>
    #include<opencv2/imgproc.hpp>
    #include<opencv2/opencv.hpp>
    usingnamespacestd;
    usingnamespace cv;
    // 构建高斯金字塔
    voidbuildGaussianPyramid(Mat& image, vector<Mat>& pyramid, int levels){
    Mat temp = image.clone();
    pyramid.push_back(temp);
    for (int i = 1; i < levels; i++) {
    // 高斯滤波
    Mat blurred;
    GaussianBlur(temp, blurred, Size(55), 0);
    Mat downSampled(blurred.rows / 2, blurred.cols / 2, blurred.type());
    resize(blurred, downSampled, downSampled.size(), 00, INTER_LINEAR);
    pyramid.push_back(downSampled);
    temp = downSampled;
    }
    }
    // 构建拉普拉斯金字塔
    voidbuildLaplacianPyramid(vector<Mat>& pyramid,vector<Mat>& laplacianPyramid){
    for (int i = 0; i < pyramid.size()-1; i++) {
    Mat upSampled(pyramid[i+1].rows * 2, pyramid[i+1].cols * 2, pyramid[i+1].type());
    resize(pyramid[i+1], upSampled, upSampled.size(), 00, INTER_LINEAR);
    Mat lap;
    subtract(pyramid[i], upSampled, lap);
    laplacianPyramid.push_back(lap);
    }
    }
    intmain(){
    Mat src = imread(".../lotus.jpg");
    int numLevels = 4;
    vector<Mat> pyramid;
    buildGaussianPyramid(src,pyramid,numLevels);
    vector<Mat> laplacianPyramid;
    buildLaplacianPyramid(pyramid,laplacianPyramid);
    for (int i = 0; i < laplacianPyramid.size(); i++) {
    imshow("Laplacian Pyramid Level " + to_string(i), laplacianPyramid[i]);
    }
    waitKey(0);
    return0;
    }








    拉普拉斯金字塔第0层.png

    拉普拉斯金字塔第1层.png

    拉普拉斯金字塔第2层.png

    OpenCV 也提供了 pyrUp() 函数来构建拉普拉斯金字塔,该函数先对图像进行升采样(将图像尺寸行和列方向增大一倍),然后再进行高斯平滑。

    pyrUp() pyrDown() 不是互逆的操作。

    #include<opencv2/core.hpp>
    #include<opencv2/imgproc.hpp>
    #include<opencv2/opencv.hpp>
    usingnamespacestd;
    usingnamespace cv;
    // 构建拉普拉斯金字塔
    voidbuildLaplacianPyramid(Mat& image, vector<Mat>& laplacianPyramid, int levels){
    Mat temp = image.clone();
    for (int i = 0; i < levels; i++) {
    Mat downSampled,upSampled;
    pyrDown(temp, downSampled);
    pyrUp(downSampled,upSampled);
    Mat lap;
    subtract(temp, upSampled, lap);
    laplacianPyramid.push_back(lap);
    temp = downSampled;
    }
    }
    intmain(){
    Mat src = imread(".../lotus.jpg");
    vector<Mat> laplacianPyramid;
    buildLaplacianPyramid(src,laplacianPyramid,3);
    for (int i = 0; i < laplacianPyramid.size(); i++) {
    imshow("Laplacian Pyramid Level " + to_string(i), laplacianPyramid[i]);
    }
    waitKey(0);
    return0;
    }




    5. 总结

    图像金字塔是一种重要的图像处理技术,它具有尺度不变性、特征提取、图像融合、图像压缩和图像增强等多种用途。本文详细介绍了三种常见图像金字塔,它们的原理、应用场景以及构建方式。

    好书推荐

    【OpenCV4应用开发:入门、进阶与工程化实践】 全书共计16个章节,重点聚焦OpenCV开发常用模块详解与工程化开发实践,提升OpenCV应用开发能力,助力读者成为OpenCV开发者,同时包含深度学习模型训练与部署加速等知识,帮助OpenCV开发者进一步拓展技能地图,满足工业项目落地所需技能提升。购买请点链接:

    https://item.jd.com/10092255924058.html

    学习课程有专属答疑群

    负责贴身答疑解惑

    读者专属QQ群 :657875553

    进群暗号:OpenCV4读者