第11章:图像金字塔
第11章:圖像金字塔
- 一、理論基礎(chǔ):
- 1. 向下采樣:
- 2. 向上采樣:
- 二、pyrDown函數(shù)使用:
- 三、pyrUp函數(shù)及使用:
- 四、采樣可逆性研究
- 五、拉普拉斯金字塔
- 1. 定義:
- 2. 應(yīng)用:
什么是圖像金子塔?
? 圖像金字塔是由一幅圖像的多個(gè)不同分辨率的子圖構(gòu)成的圖像集合。是通過(guò)一個(gè)圖像不斷的降低采樣率產(chǎn)生的,最小的圖像可能僅僅有一個(gè)像素點(diǎn)。下圖是一個(gè)圖像金子塔的示例。從圖中可以看到,圖像金字塔是一系列以金字塔形狀排列的、自底向上分辨率逐漸降低的圖像集合。
? 通常情況下,圖像金字塔的底部是待處理的高分辨率圖像(原始圖像),而頂部則為其低分辨率的近似圖像。向金字塔頂部移動(dòng)時(shí),圖像的尺寸和分辨率都不斷地降低。通常情況下,每向上移動(dòng)一級(jí),圖像的寬和高都降低為原來(lái)的二分之一。
一、理論基礎(chǔ):
? 圖像金字塔是同一圖像不同分辨率的子圖集合,是通過(guò)原圖像不斷地向下降低采樣而產(chǎn)生的,即由高分辨率的圖像(大尺寸)產(chǎn)生低分辨率的近似圖像(小尺寸)。
1. 向下采樣:
? 最簡(jiǎn)單的圖像金字塔可以通過(guò)不斷的刪除圖像的偶數(shù)行和偶數(shù)列得到的。例如,有一幅圖像,其大小是N*N,刪除其偶數(shù)行和偶數(shù)列后得到一幅(N/2)*(N/2)大小的圖像。經(jīng)過(guò)上述處理后,圖像的大小變?yōu)樵瓉?lái)的四分之一,不斷重復(fù)該過(guò)程,就可以得到該圖像的圖像金字塔。
? 也可以通過(guò)先對(duì)原始圖像濾波,得到原始圖像的近似圖像,然后將近似圖像的偶數(shù)行和偶數(shù)列刪除以獲取向下采樣的結(jié)果。有多種濾波器可以選擇。
-
領(lǐng)域?yàn)V波器:采用鄰域平均值計(jì)算求原始圖像的近似圖像。該濾波器能夠產(chǎn)生平均金字塔。
-
高斯濾波器:采用高斯濾波器對(duì)原始圖像進(jìn)行濾波,得到高斯金字塔。這是OpenCV函數(shù)cv2.pyrDown()所采用的的方式。
高斯金字塔是通過(guò)不斷地使用高斯金字塔濾波、采樣所產(chǎn)生的,其過(guò)程如下:
? 經(jīng)過(guò)上述處理后,原始圖像與各次向下采樣所得到的結(jié)果圖像共同構(gòu)成了高斯金字塔。例如,可以將原始圖像稱為第0層,第1次向下采樣的結(jié)果圖像稱為第一層、第2次向下采樣的結(jié)果圖像稱為第2層,以此類推。上述圖像所構(gòu)成的高斯金字塔如圖所示。
? 下面為了表述統(tǒng)一,我們一律將圖像金字塔中底層稱為第0層,底層上面一層稱為第1層,并以此類推。
2. 向上采樣:
? 在向上采樣的過(guò)程中,通常將圖像的寬度和高度都變?yōu)樵瓉?lái)的2倍。這意味著,向上采樣的結(jié)果圖像的大小是原始圖像的4倍。因此,要在結(jié)果圖像中補(bǔ)充大量的像素點(diǎn)。對(duì)新生成的像素點(diǎn)進(jìn)行賦值的行為,稱為 插值。該過(guò)程可以通過(guò)多種方式實(shí)現(xiàn),例如最鄰近插值就是使用最鄰近的像素點(diǎn)給當(dāng)前還沒(méi)有值的像素點(diǎn)賦值。
? 還有一種常見(jiàn)的向上采樣,對(duì)像素點(diǎn)以補(bǔ)零的方式完成插值。通常是在每列像素點(diǎn)的右側(cè)插入值為零的列,在每行像素點(diǎn)的下方插入值為零的行。如圖,左側(cè)是要進(jìn)行向上采樣的4個(gè)像素點(diǎn),右側(cè)是向上采樣時(shí)進(jìn)行補(bǔ)零后處理結(jié)果。
? 接下來(lái),使用向下采樣時(shí)所使用的的高斯濾波器對(duì)補(bǔ)零后的圖像進(jìn)行濾波處理,以獲取向上采樣的結(jié)果圖像。 但是需要注意,此時(shí)圖像中有四分之三的像素點(diǎn)的值都是零。所以,要將高斯濾波器系數(shù)乘以4,以保證得到的像素值在其原有像素值的范圍內(nèi)。
? 例如,針對(duì)上圖右側(cè)的像素點(diǎn),其對(duì)應(yīng)的是8位圖像,像素值的范圍是[0, 255]。由于其中四分之三的像素點(diǎn)的值都是為零,如果直接使用高斯濾波器對(duì)其進(jìn)行卷積計(jì)算,會(huì)導(dǎo)致像素值的范圍變?yōu)閇0, 255*1/4]。所以,要將所使用的高斯濾波器系數(shù)乘以4,以保證得到像素值的范圍仍舊在[0, 255]內(nèi)。
? 或者,從另一個(gè)角度理解,在原始圖像內(nèi)每個(gè)像素點(diǎn)的右側(cè)列插入零值列,在每個(gè)像素點(diǎn)的下一行插入零值行,將圖像變?yōu)樵瓉?lái)的兩倍寬、兩倍高。接下來(lái),將補(bǔ)零后的圖像用高斯濾波器進(jìn)行卷積運(yùn)算。最后,將圖像內(nèi)每個(gè)像素點(diǎn)的值乘以4,以保證像素值的范圍與原始圖像一致。
? 通過(guò)以上分析可知,向上采樣和向下采樣是相反的兩種操作。但是,由于上下采樣會(huì)丟失像素值,所以兩種操作并不是可逆的。 也就是說(shuō),對(duì)一幅圖像先向上采樣、再向下采樣,是無(wú)法恢復(fù)期原始狀態(tài)的;同樣,對(duì)一幅圖像先向下采樣、再向上采樣也是無(wú)法恢復(fù)到原始狀態(tài)的。
二、pyrDown函數(shù)使用:
在OpenCV中使用函數(shù)cv2.pyrDown(),實(shí)現(xiàn)圖像高斯金字塔操作中的向下采樣,語(yǔ)法形式為:
dst = cv2.pyrDown(src [, dstsize [, borderType] ])
- dst:目標(biāo)圖像
- src:原始圖像
- dstsize:目標(biāo)圖像的大小
- borderType:邊界類型,默認(rèn)值為BORDER_DEFAULT,且這里僅支持BORDER_DEFAULT。
默認(rèn)情況下,輸出圖像的大小為Size((src.cols+1)/2, (src.rows+1)/2)。在任何情況下,圖像的尺寸必須滿足如下條件:
-
|dst.width * 2 - src.cols| ≤ 2
|dst.height * 2 - src.rows| ≤ 2
cv2.pyrDown()函數(shù)首先對(duì)原始圖像進(jìn)行高斯濾波變換,以獲取原始圖像的近似圖像。在獲取近似圖像后,該函數(shù)通過(guò)拋棄偶數(shù)行和偶數(shù)列來(lái)實(shí)現(xiàn)向下采樣。
示例:
import cv2img = cv2.imread('../lena.bmp') rst1 = cv2.pyrDown(img) rst2 = cv2.pyrDown(rst1) rst3 = cv2.pyrDown(rst2)print('img.shape=', img.shape) print('rst1.shape=', rst1.shape) print('rst2.shape=', rst2.shape) print('rst3.shape=', rst3.shape)cv2.imshow('img', img) cv2.imshow('rst1', rst1) cv2.imshow('rst2', rst2) cv2.imshow('rst3', rst3)cv2.waitKey() cv2.destroyAllWindows()# 輸出結(jié)果 img.shape= (512, 512, 3) rst1.shape= (256, 256, 3) rst2.shape= (128, 128, 3) rst3.shape= (64, 64, 3)三、pyrUp函數(shù)及使用:
在OpenCV中,使用函數(shù)cv2.pyrUp()實(shí)現(xiàn)圖像金字塔操作中的向上采樣,其語(yǔ)法格式為:
dst = cv2.pyrUp(src, [, dstsize [, borderType ] ] )
- dst:目標(biāo)圖像
- src:原始圖像
- dstsize:目標(biāo)圖像的大小
- borderType:邊界類型,默認(rèn)值為BORDER_DEFAULT,且這里僅支持BORDER_DEFAULT。
默認(rèn)情況下,輸出圖像的大小為Size(src.cols*2, src.rows*2)。在任何情況下,圖像的尺寸必須滿足如下條件:
-
|dst.width - src.cols * 2| ≤ mod(dst.widh, 2)
|dst.height - src.rows * 2| ≤ mod(dst.height, 2)
? 在使用cv2.pyrUp()函數(shù)對(duì)圖像向上采樣時(shí),在每個(gè)像素的右側(cè)、下方分別插入零值列和零值行,得到一個(gè)偶數(shù)行、偶數(shù)列(即新增的行、列)都是零值的新圖像New。接下來(lái),用向下采樣時(shí)所使用的高斯濾波器對(duì)新圖像New進(jìn)行濾波,得到向上采樣的結(jié)果圖像。需要注意的是,為了確保像素值的區(qū)間在向上采樣后與原始圖像保持一致,需要將高斯濾波器的系數(shù)乘以4。
示例:
import cv2img = cv2.imread('../boat.512.tiff') rst1 = cv2.pyrUp(img) rst2 = cv2.pyrUp(rst1) rst3 = cv2.pyrUp(rst2)print('img.shape=', img.shape) print('rst1.shape=', rst1.shape) print('rst2.shape=', rst2.shape) print('rst3.shape=', rst3.shape)cv2.imshow('img', img) cv2.imshow('rst1', rst1) cv2.imshow('rst2', rst2) cv2.imshow('rst3', rst3)cv2.waitKey() cv2.destroyAllWindows()# 輸出結(jié)果 img.shape= (64, 64, 3) rst1.shape= (128, 128, 3) rst2.shape= (256, 256, 3) rst3.shape= (512, 512, 3)四、采樣可逆性研究
? 圖像在向上采樣后,整體尺寸變?yōu)樵瓉?lái)的4倍;在向下采樣后,整體尺寸變?yōu)樵瓉?lái)的四分之一。下圖展示了圖像在采樣前后的大小變化關(guān)系。一幅M*N大小的圖像經(jīng)過(guò)向下采樣后大小會(huì)變?yōu)?M/2)*(N/2);一幅M*N大小的圖像經(jīng)過(guò)向上采樣后大小會(huì)變?yōu)?2M)*(2N)
? 雖然一幅圖像在先后經(jīng)過(guò)向下采樣、向上采樣后,會(huì)恢復(fù)原始大小,但是向上采樣和向下采樣不是互逆的。也就是說(shuō),雖然在經(jīng)歷兩次采樣操作后,得到的結(jié)果圖像與原始圖像的大小一致,肉眼看起來(lái)也相似,但是二者的像素并不是一致的。
示例:
import cv2img = cv2.imread('../boat.512.tiff')down = cv2.pyrDown(img) up = cv2.pyrUp(down) diff = up - img print('img.shape=', img.shape) print('down.shape=', up.shape) cv2.imshow('img', img) cv2.imshow('up', up) cv2.imshow('diff', diff) cv2.waitKey() cv2.destroyAllWindows()# 輸出結(jié)果 img.shape= (512, 512, 3) down.shape= (512, 512, 3)五、拉普拉斯金字塔
? 前面所介紹的高斯金字塔,是通過(guò)對(duì)一幅圖像一系列的向下采樣所產(chǎn)生的。有時(shí),我們希望通過(guò)對(duì)金字塔中的小圖像進(jìn)行向上采樣以獲取完整的大尺寸高分辨率圖像,這時(shí)就需要用到拉普拉斯金字塔。
1. 定義:
? 一幅圖像在經(jīng)過(guò)向下采樣后,在對(duì)其進(jìn)行向上采樣,是無(wú)法恢復(fù)為原始狀態(tài)的。對(duì)此,我們也用程序進(jìn)行了驗(yàn)證。向上采樣并不是向下采樣的逆運(yùn)算。這很明顯,因?yàn)橄蛳虏蓸訒r(shí)在使用高斯濾波器處理后還要拋棄偶數(shù)行,偶數(shù)列,不可避免的要丟失一些信息。
? 為了在向上采樣是能夠恢復(fù)具有較高分辨率的原始圖像,就要獲取在采樣過(guò)程中所丟失的信息,這些丟失的信息就構(gòu)成了拉普拉斯金字塔。 也是拉普拉斯金字塔是有向下采樣時(shí)丟失的信息構(gòu)成。
拉普拉斯金字塔的定義形式為:
- Li = Gi - pyrUp( Gi + 1 )
式中:
- Li:表示拉普拉斯金字塔中的第i層
- Gi:表示高斯金字塔中的第i層
? 拉普拉斯金字塔中的第i層,等于"高斯金字塔中的第i層"與"高斯金字塔中的第 i + 1層的向上采樣結(jié)果"之差。下圖展示了高斯金字塔和拉普拉斯金字塔的對(duì)應(yīng)關(guān)系。
示例:使用cv2.pyrDown()和cv2.pyrUp()構(gòu)造拉普拉斯金子塔
import cv2img = cv2.imread('../boat.512.tiff') G1 = cv2.pyrDown(img) G2 = cv2.pyrDown(G1) G3 = cv2.pyrDown(G2)L0 = img - cv2.pyrUp(G1) L1 = G1 - cv2.pyrUp(G2) L2 = G2 - cv2.pyrUp(G3)print('L0.shape=', L0.shape) print('L1.shape=', L1.shape) print('L2.shape=', L2.shape)cv2.imshow('L0', L0) cv2.imshow('L1', L1) cv2.imshow('L2', L2) cv2.waitKey() cv2.destroyAllWindows()# 輸出結(jié)果 L0.shape= (512, 512, 3) L1.shape= (256, 256, 3) L2.shape= (128, 128, 3)2. 應(yīng)用:
拉普拉斯金字塔的作用在于,能夠恢復(fù)高分辨率的圖像。下圖演示了如何通過(guò)拉普拉斯金字塔恢復(fù)高分辨率圖像。
圖中各標(biāo)記含義如下:
- G0、G1、G2、G3分別是高斯金字塔的第0層、第1層、第2層、第3層。
- L0、L1、L2、分別是拉普拉斯金字塔的第0層、第1層、第2層。
- 向下的箭頭表示向下采樣操作(對(duì)應(yīng)cv2.pyrDown()函數(shù))
- 向右的箭頭表示向上采樣操作(對(duì)應(yīng)cv2.pyrUp() 函數(shù))
- "+"表示加法操作
- "-"表示減法操作
上圖中的操作關(guān)系有:
向下采樣:
- G1 = cv2.pyrDown(G0)
- G2 = cv2.pyrDown(G1)
- G3 = cv2.pyrDown(G2)
拉普拉斯金字塔:
- L0 = G0 - cv2.pyrUp(G1)
- L1 = G1 - cv2.pyrUp(G2)
- L2 = G2 - cv2.pyrUp(G3)
向上采樣恢復(fù)高分辨率圖像:
- G0 = L0 + cv2.pyrUp(G1)
- G1 = L1 + cv2.pyrUp(G2)
- G2 = L2 + cv2.pyrUp(G3)
上述關(guān)系是通過(guò)數(shù)學(xué)運(yùn)算推導(dǎo)得到的。例如,已知L0=G0-cv2.pyrUp(G1),將表達(dá)式右側(cè)的cv2.pyrUp(G1)移到左側(cè),就得到了表達(dá)式G0 = L0 + cv2.pyrUp(G1)。除此之外,G1和G2都可以通過(guò)拉普拉斯金字塔的構(gòu)造表達(dá)式得到。如之前介紹的,拉普拉斯金字塔的目的就是為了恢復(fù)高分辨率的圖像。
示例:使用拉普拉斯金字塔恢復(fù)高分辨率的圖像
import cv2 import numpy as npimg = cv2.imread('../boat.512.tiff')G0 = img G1 = cv2.pyrDown(G0) G2 = cv2.pyrDown(G1) G3 = cv2.pyrDown(G2)L0 = G0 - cv2.pyrUp(G1) L1 = G1 - cv2.pyrUp(G2) L2 = G2 - cv2.pyrUp(G3)rst_G0 = L0 + cv2.pyrUp(G1) rst_G1 = L1 + cv2.pyrUp(G2) rst_G2 = L2 + cv2.pyrUp(G3)print('rst_G0', np.sum(abs(G0 - rst_G0))) print('rst_G1', np.sum(abs(G1 - rst_G1))) print('rst_G2', np.sum(abs(G2 - rst_G2)))cv2.imshow('G0', G0) cv2.imshow('G1', G1) cv2.imshow('G2', G2)cv2.imshow('rst_G0', rst_G0) cv2.imshow('rst_G1', rst_G1) cv2.imshow('rst_G2', rst_G2)cv2.waitKey() cv2.destroyAllWindows()總結(jié)
以上是生活随笔為你收集整理的第11章:图像金字塔的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 美国要求签证申请人提供社交媒体账号 不给
- 下一篇: JAVA IO操作笔记