當前位置: 妍妍網 > 碼農

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讀者