1. 程式人生 > >Python3+OpenCV3影象處理(十一)—— 影象金字塔

Python3+OpenCV3影象處理(十一)—— 影象金字塔

簡介:影象金字塔是影象中多尺度表達的一種,最主要用於影象的分割,是一種以多解析度來解釋影象的有效但概念簡單的結構。簡單來說,影象金字塔就是用來進行影象縮放的。

進行影象縮放可以用影象金字塔,也可以使用resize函式進行縮放,後者效果更好。這裡只是對影象金字塔做一些簡單瞭解。

兩種型別的金字塔:

①高斯金字塔:用於下采樣。高斯金字塔是最基本的影象塔。原理:首先將原影象作為最底層影象G0(高斯金字塔的第0層),利用高斯核(5*5)對其進行卷積,然後對卷積後的影象進行下采樣(去除偶數行和列)得到上一層影象G1,將此影象作為輸入,重複卷積和下采樣操作得到更上一層影象,反覆迭代多次,形成一個金字塔形的影象資料結構,即高斯金字塔。

②拉普拉斯金字塔:用於重建影象,也就是預測殘差,對影象進行最大程度的還原。比如一幅小影象重建為一幅大圖,原理:用高斯金字塔的每一層影象減去其上一層影象上取樣並高斯卷積之後的預測影象,得到一系列的差值影象即為 LP 分解影象。

兩種型別的取樣:

①上取樣:就是圖片放大(所謂上嘛,就是變大),使用PryUp函式。    上取樣步驟:先將影象在每個方向放大為原來的兩倍,新增的行和列用0填充,再使用先前同樣的核心與放大後的影象卷積,獲得新增畫素的近似值。     

②下采樣:就是圖片縮小(所謂下嘛,就是變小),使用PryDown函式。下采樣將步驟:先對影象進行高斯核心卷積 ,再將所有偶數行和列去除。

總之,上、下采樣都存在一個嚴重的問題,那就是影象變模糊了,因為縮放的過程中發生了資訊丟失的問題。要解決這個問題,就得用拉普拉斯金字塔。

參考部落格:

程式碼如下:

複製程式碼

import cv2 as cv
#高斯金字塔
def pyramid_demo(image):
    level = 3      #設定金字塔的層數為3
    temp = image.copy()  #拷貝影象
    pyramid_images = []  #建立一個空列表
    for i in range(level):
        dst = cv.pyrDown(temp)   #先對影象進行高斯平滑,然後再進行降取樣(將影象尺寸行和列方向縮減一半)
        pyramid_images.append(dst)  #在列表末尾新增新的物件
        cv.imshow("pyramid"+str(i), dst)
        temp = dst.copy()
    return pyramid_images
#拉普拉斯金字塔
def lapalian_demo(image):
    pyramid_images = pyramid_demo(image)    #做拉普拉斯金字塔必須用到高斯金字塔的結果
    level = len(pyramid_images)
    for i in range(level-1, -1, -1):
        if (i-1) < 0:
            expand = cv.pyrUp(pyramid_images[i], dstsize = image.shape[:2])
            lpls = cv.subtract(image, expand)
            cv.imshow("lapalian_down_"+str(i), lpls)
        else:
            expand = cv.pyrUp(pyramid_images[i], dstsize = pyramid_images[i-1].shape[:2])
            lpls = cv.subtract(pyramid_images[i-1], expand)
            cv.imshow("lapalian_down_"+str(i), lpls)
src = cv.imread('E:/imageload/zixia.jpg')
cv.namedWindow('input_image', cv.WINDOW_AUTOSIZE) #設定為WINDOW_NORMAL可以任意縮放
cv.imshow('input_image', src)
lapalian_demo(src)
cv.waitKey(0)
cv.destroyAllWindows()

複製程式碼

執行結果:

注意:

1.opencv的pyrDown函式先對影象進行高斯平滑,然後再進行降取樣(將影象尺寸行和列方向縮減一半)。其函式原型為:pyrDown(src[, dst[, dstsize[, borderType]]]) -> dst

src引數表示輸入影象。

dst引數表示輸出影象,它與src型別、大小相同。

dstsize引數表示降取樣之後的目標影象的大小。它是有預設值的,如果我們呼叫函式的時候不指定第三個引數,那麼這個值是按照 Size((src.cols+1)/2, (src.rows+1)/2) 計算的。而且不管你自己如何指定這個引數,一定必須保證滿足以下關係式:|dstsize.width * 2 - src.cols| ≤ 2;  |dstsize.height * 2 - src.rows| ≤ 2。也就是說降取樣的意思其實是把影象的尺寸縮減一半,行和列同時縮減一半。

borderType引數表示表示影象邊界的處理方式。

2.opencv的pyrUp函式先對影象進行升取樣(將影象尺寸行和列方向增大一倍),然後再進行高斯平滑。其函式原型為:pyrUp(src[, dst[, dstsize[, borderType]]]) -> dst

src引數表示輸入影象。

dst引數表示輸出影象,它與src型別、大小相同。

dstsize引數表示降取樣之後的目標影象的大小。在預設的情況下,這個尺寸大小是按照 Size(src.cols*2, (src.rows*2) 來計算的。如果你自己要指定大小,那麼一定要滿足下面的條件:

|dstsize.width - src.cols * 2| ≤ (dstsize.width mod 2);  //如果width是偶數,那麼必須dstsize.width是src.cols的2倍

|dstsize.height - src.rows * 2| ≤ (dstsize.height mod 2);

borderType引數表示表示影象邊界的處理方式。

參考:

注意:拉普拉斯金字塔時,影象大小必須是2的n次方*2的n次方,不然會報錯?(只要影象長和寬相等即可,並不非要是2的n次方*2的n次方,至少我這麼做沒問題,也不知道為什麼都說影象大小必須是2的n次方*2的n次方,求知道的大佬告知一波!