目錄
1 圖像金字塔簡介
以多個分辨率來表示圖像的一種有效且概念簡單的結構是圖像金字塔。圖像金字塔最初用於機器視覺和圖像壓縮,一個圖像金字是一系列以金字塔形狀排列的、分辨率逐步降低的圖像集合。
如圖下圖所示,它包括了四層圖像,將這一層一層的圖像比喻成金字塔。圖像金字塔可以通過梯次向下採樣獲得,直到達到某個終止條件才停止採樣,在向下採樣中,層級越高,則圖像越小,分辨率越低。
生成圖像金字塔主要包括兩種方式:向下取樣 和 向上取樣。
如下圖所示:
向下取樣:將圖像從G0轉換爲G1、G2、G3,圖像分辨率不斷降低的過程;
向上取樣:將圖像從G3轉換爲G2、G1、G0,圖像分辨率不斷增大的過程。
下面將依次介紹向下取樣 和 向上取樣。
2 向下取樣——pyrDown()
2.1 基礎理論
在圖像向下取樣中,一般分兩步:
(1)對圖像Gi進行高斯卷積核(高斯濾波);
(2)刪除所有的偶數行和列。
其中,高斯核卷積運算(高斯濾波)就是對整幅圖像進行加權平均的過程,每一個像素點的值,都由其本身和鄰域內的其他像素值(權重不同)經過加權平均後得到。常見的 33 和 55 高斯核如下:
關於高斯濾波的詳細過程,可以參見博客:圖像平滑 (均值濾波、中值濾波和高斯濾波)
如下圖所示,向下取樣後,原始圖像 具有 MN 個像素,進行向下取樣之後,所得到的圖像 +1 具有 M/2 N/2 個像素,只有原圖的四分之一。通過對輸入的原始圖像不停迭代以上步驟就會得到整個金字塔。
注:由於每次向下取樣會刪除偶數行和列,所以它會不停地丟失圖像的信息。
下面是向下取樣的圖像,可以看到圖像不斷縮小。
2.2 代碼示例
在OpenCV中,向下取樣使用的函數爲pyrDown(),其函數用法如下所示:
dst = pyrDown(src[, dst[, dstsize[, borderType]]])
其中,參數:
src 表示輸入圖像;
dst 表示輸出圖像,和輸入圖像具有一樣的尺寸和類型;
dstsize 表示輸出圖像的大小,默認值爲Size();
borderType 表示像素外推方法,詳見cv::bordertypes 。
(1)一次向下採樣
代碼如下所示:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取原始圖像
img = cv2.imread('zxp.jpg')
#圖像向下取樣
r = cv2.pyrDown(img)
#顯示圖像
cv2.imshow('original', img)
cv2.imshow('PyrDown', r)
cv2.waitKey()
cv2.destroyAllWindows()
運行結果如下圖所示:
(2)多次向下採樣
代碼如下所示:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取原始圖像
img = cv2.imread('zxp.jpg')
#圖像向下取樣
r1 = cv2.pyrDown(img)
r2 = cv2.pyrDown(r1)
r3 = cv2.pyrDown(r2)
#顯示圖像
cv2.imshow('original', img)
cv2.imshow('PyrDown1', r1)
cv2.imshow('PyrDown2', r2)
cv2.imshow('PyrDown3', r3)
cv2.waitKey()
cv2.destroyAllWindows()
運行結果如下圖所示:
3 向上取樣——pyrUp()
3.1 基礎理論
在圖像向上取樣是由小圖像不斷放圖像的過程。它將圖像在每個方向上擴大爲原圖像的2倍,新增的行和列均用0來填充,並使用與“向下取樣”相同的卷積核乘以4,再與放大後的圖像進行卷積運算,以獲得“新增像素”的新值。
如圖下圖所示,它在原始像素45、123、89、149之間各新增了一行和一列值爲0的像素。
如下圖所示,爲圖像的向上採樣和向下採樣的例子。
注:向上取樣和向下取樣無法互逆的。
3.2 代碼示例
在OpenCV中,向上取樣使用 pyrUp() 函數,其函數用法如下所示:
dst = pyrUp(src[, dst[, dstsize[, borderType]]])
其中,參數:
src 表示輸入圖像;
dst 表示輸出圖像,和輸入圖像具有一樣的尺寸和類型;
dstsize 表示輸出圖像的大小,默認值爲Size();
borderType 表示像素外推方法,詳見cv::bordertypes 。
代碼如下所示:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取原始圖像
img = cv2.imread('zxp_PyrDown2.jpg')
#圖像向上取樣
r = cv2.pyrUp(img)
#顯示圖像
cv2.imshow('original', img)
cv2.imshow('PyrUp', r)
cv2.waitKey()
cv2.destroyAllWindows()
運行結果如下圖所示:
4 Laplacian 金字塔
4.1 基礎理論
前面提到的均是高斯金字塔(使用高斯核),下面介紹拉普拉斯(Laplacian) 金字塔,拉普拉斯(Laplacian) 金字塔是在高斯金字塔的基礎上新的金字塔。
如下圖所示,拉普拉斯(Laplacian) 金字塔的表達式:
拉普拉斯每一層表示如下圖所示:
下圖高斯金字塔和拉普拉斯金字塔 交叉使用得到不同的圖像。
4.2 代碼示例
(1) 拉普拉斯第0層
代碼如下所示:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取原始圖像
img = cv2.imread('lena.tiff')
#圖像向下取樣
r1 = cv2.pyrDown(img)
#圖像向上取樣
r2 = cv2.pyrUp(r1)
# 拉普拉斯第0層
LapPyr0 =img-r2
#顯示圖像
cv2.imshow('original', img)
cv2.imshow('LapPyr', LapPyr0)
cv2.waitKey()
cv2.destroyAllWindows()
運行結果如下圖所示:
(2) 拉普拉斯第0層和拉普拉斯第1層
代碼如下所示:
# -*- coding: utf-8 -*-
import cv2
import numpy as np
import matplotlib.pyplot as plt
#讀取原始圖像
img = cv2.imread('lena.tiff')
#圖像向下取樣
r1 = cv2.pyrDown(img)
#圖像向上取樣
r2 = cv2.pyrUp(r1)
# 拉普拉斯第0層
LapPyr0 =img-r2
#圖像向下取樣
r3 = cv2.pyrDown(r1)
#圖像向上取樣
r4 = cv2.pyrUp(r3)
# 拉普拉斯第1層
LapPyr1 =r1-r4
#顯示圖像
cv2.imshow('original', img)
cv2.imshow('LapPyr0', LapPyr0)
cv2.imshow('LapPyr1', LapPyr1)
cv2.waitKey()
cv2.destroyAllWindows()
運行結果如下圖所示:
參考資料
[1] https://blog.csdn.net/Eastmount/article/details/89341077