- 圖像處理與計算機視覺實踐:基于OpenCV和Python
- 吳佳 于仕琪編著
- 1340字
- 2023-10-17 18:55:05
2.1 縮放
縮放是最簡單的仿射變換,顧名思義,應用它可將圖像放大或縮小。圖2-2所示是一幅原始圖像,圖2-3(a)所示是縮小后的圖像,圖2-3(b)所示是放大后的圖像。

圖2-2 原始圖像

(a)

(b)
圖2-3 圖2-2縮放后的圖像
將圖像放大或縮小后會得到新圖像,比如將100×100的圖像放大為200×200,如果原始圖像有1萬個像素點,那么新圖像中有4萬個像素點,這4萬個像素點的值應該怎么根據原始圖像的像素值來計算呢?這就需要用到一個重要的技術——插值。
我們先來看一個例子。如圖2-4所示,有一幅大小為3×3的圖像,將其按長寬等比例放大4/3倍后得到一幅4×4的新圖像,新圖像中(2, 1)位置的像素對應于原始圖像(1.5, 0.75)位置。但是原始圖像的像素都位于整數坐標位置,于是新圖像在原始圖像中的對應點(1.5, 0.75)位置的像素值就需要根據其周圍在整數位置的像素值來計算得出,比如可以用圖2-4(a)中深色區域的4個像素來計算,這就是插值。
最簡單的插值方法就是直接取距離(1.5, 0.75)最近的整數位置像素的值,這種方法叫作最近鄰插值。
雙線性插值是一種常用的插值方法,它是線性插值的擴展。在數學上,線性插值是一種曲線擬合的方法,它通過線性多項式來計算已知相鄰數據點之間的點。如圖2-5所示,假設已知和
兩點,用線性插值可以計算出這兩點間連線上的點,也就是說給出x0和x1間的一個值x,對應的y值可用下面的式(2-1)計算得出:

即

式(2-1)

(a) ?。╞)
圖2-4 插值

圖2-5 線性插值
對線性插值進行擴展,在兩個方向上分別進行一次線性插值,即對x和y都進行插值,這樣的方法就稱為雙線性插值。如圖2-6所示,我們需要得到點的值,假設已知
、
、
和
這4個點的值。

圖2-6 雙線性插值
先在x軸方向進行線性插值,得到和
點的值:


式(2-2)
然后在y軸方向根據點和
進行線性插值,便得到點P的值:

式(2-3)
雙線性插值的結果與插值順序無關,先進行x軸方向插值和先進行y軸方向插值的最終結果是一樣的。需要注意的是,雙線性插值并不是線性的,而是非線性的。對于其他的插值方法,感興趣的讀者可以查閱相關資料進行了解。
OpenCV提供了對圖像進行縮放的函數cv.resize(),該函數支持多種插值方法。
dst = cv.resize(src, dsize[, fx[, fy[, interpolation]]])
其中的主要參數介紹如下。
● dst:輸出圖像,大小為dsize,或由src的大小、fx和fy計算得到。
● src:輸入圖像。
● dsize:輸出圖像的大小。如果其為None,則

● fx:圖像寬的縮放比例。如果該值為0,則按計算得出。
● fy:圖像高的縮放比例。如果該值為0,則按計算得出。
● interpolation:插值方法。插值方法和說明如表2-1所示。默認的插值方法是雙線性插值INTER_LINEAR。
表2-1 插值方法和說明

不同的插值方法會產生不同質量的圖像,同時它們的計算速度也不一樣。圖2-7中的4幅圖為采用不同的插值方法將圖2-2放大2倍后的圖像,圖2-7(a)~圖2-7(d)依次為使用最近鄰插值、雙線性插值、雙三次插值和LANCZOS插值得到的新圖像。對比結果可以看出,最近鄰插值會讓圖像產生鋸齒效果,雙線性插值會讓圖像邊緣變模糊,而雙三次插值和LANCZOS插值的效果均較好。從速度上看,這4種插值方法中,最近鄰插值速度最快,雙線性插值的速度較快,雙三次插值的速度一般,而LANCZOS插值的速度最慢。

(a)

(b)

(c)

(d)
圖2-7 使用不同的插值方法將圖2-2放大2倍后的圖像
實現代碼如下:
import cv2 as cv import numpy as np def main(): # 讀入圖像 im = cv.imread('lena.jpg') cv.imshow('lena.jpg', im) # 縮放圖像 dim = (int(im.shape[1]*2), int(im.shape[0]*2)) im_rs_nr = cv.resize(im, dim, interpolation=cv.INTER_NEAREST) im_rs_ln = cv.resize(im, dim, interpolation=cv.INTER_LINEAR) im_rs_cb = cv.resize(im, dim, interpolation=cv.INTER_CUBIC) im_rs_lz = cv.resize(im, dim, interpolation=cv.INTER_LANCZOS4) cv.imshow('lena_rs_nr.jpg', im_rs_nr) cv.imshow('lena_rs_ln.jpg', im_rs_ln) cv.imshow('lena_rs_cb.jpg', im_rs_cb) cv.imshow('lena_rs_lz.jpg', im_rs_lz) cv.waitKey() cv.destroyAllWindows() if __name__ == '__main__': main()