圖像縮放¶
概要¶
本節介紹了使用resize
函數與wrapAffine
兩種方式實現圖像縮放.
keywords 圖像縮放 resize wrapAffine
利用resize函數實現縮放¶
opencv其實有專門進行圖像縮放的函數resize
。
resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) -> dst
參數解析
-
src
輸入圖片 -
dsize
輸出圖片的尺寸 -
dst
輸出圖片 -
fx
x軸的縮放因子 -
fy
y軸的縮放因子 -
interpolation
插值方式 -
INTER_NEAREST
- 最近鄰插值 -
INTER_LINEAR
- 線性插值(默認) -
INTER_AREA
- 區域插值 -
INTER_CUBIC
- 三次樣條插值 -
INTER_LANCZOS4
- Lanczos插值
在使用的時候, 我們可以傳入指定的圖片的尺寸dsize
src/resize_cat.py
''' 使用resize函數對圖像進行縮放 ''' import cv2 import numpy as np img = cv2.imread('cat.jpg') height,width,channel = img.shape # 聲明新的維度 new_dimension = (400, 400) # 指定新圖片的維度與插值算法(interpolation) resized = cv2.resize(img, new_dimension) cv2.imwrite('cat_resize_400_400.png', resized)
或者指定縮放因子
f_x, f_y
將dsize
設置為 None
然后指定fx
fy
import cv2 import numpy as np img = cv2.imread('cat.png') height,width,channel = img.shape # 指定新圖片的維度與插值算法(interpolation) resized = cv2.resize(img, None, fx=1.5, fy=2) cv2.imwrite('cat_resize_fx_fy.png', resized)
或者指定輸出圖片,并傳入輸出圖片的size。
src/resize_cat_v2.py
''' 根據fx跟fy進行圖像縮放 ''' import cv2 import numpy as np img = cv2.imread('cat.jpg') height,width,channel = img.shape # 指定輸出圖片 dst = np.zeros((100, 100, 3), dtype='uint8') # 指定新圖片的維度與插值算法(interpolation) cv2.resize(img, dst=dst, dsize=(dst.shape[1], dst.shape[0]), fx=1.5, fy=2) cv2.imwrite('cat_resize_from_dst.png', dst)
更詳細的使用說明見opencv-resize 文檔
為了方便使用, 我們也可以將其封裝成函數
def resize(image, width = None, height = None, inter = cv2.INTER_AREA): dim = None (h, w) = image.shape[:2] if width is None and height is None: return image if width is None: r = height / float(h) dim = (int(w * r), height) if height is None: r = width / float(w) dim = (width, int(h * r)) if width and height: dim = (width, height) resized = cv2.resize(image, dim, interpolation = inter) return resized
分辨率 從5*5 放大到1000*1000, 選擇不同的插值算法,對應的演示效果。
src/resize_interpolation.py
''' 差值算法對比 ''' import cv2 import numpy as np from matplotlib import pyplot as plt img = np.uint8(np.random.randint(0,255,size=(5,5))) height,width= img.shape # 聲明新的維度 new_dimension = (1000, 1000) plt.subplot(231) plt.title("SRC Image") plt.imshow(img,cmap='seismic') plt.subplot(232) resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_NEAREST) plt.title("INTER_NEAREST") plt.imshow(resized,cmap='seismic') plt.subplot(233) resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_LINEAR) plt.title("INTER_LINEAR") plt.imshow(resized,cmap='seismic') plt.subplot(234) resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_AREA) plt.title("INTER_AREA") plt.imshow(resized,cmap='seismic') plt.subplot(235) resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_CUBIC) plt.title("INTER_CUBIC") plt.imshow(resized,cmap='seismic') plt.subplot(236) resized = cv2.resize(img, new_dimension, interpolation = cv2.INTER_LANCZOS4) plt.title("INTER_LANCZOS4") plt.imshow(resized,cmap='seismic') plt.show()
!!學霸分割線!!
如果你對圖像縮放
的數學原理不感興趣的話,就不需要往下看了.
利用wrapAffine實現縮放¶
對圖像的伸縮變換的變換矩陣M為
\begin{equation}
{
\left[ \begin{array}{c}
x'\\
y'\\
\end{array}
\right ]}=
{
\left[ \begin{array}{cc}
f_x & 0\\
0 & f_y\\
\end{array}
\right ]}\times
{
\left[\begin{array}{c}
x\\
y\\
\end{array}
\right]
}+
{
\left[\begin{array}{c}
0\\
0\\
\end{array}
\right]
}
\end{equation}
其中,
f_x
代表x軸的焦距(縮放因子),
f_y
代表y軸的焦距(縮放因子)。
x' = f_x * x
y' = f_y*y
''' 使用仿射矩陣實現 ''' import numpy as np import cv2 img = cv2.imread('cat.jpg') height,width,channel = img.shape # x軸焦距 1.5倍 fx = 1.5 # y軸焦距 2倍 fy = 2 # 聲明變換矩陣 向右平移10個像素, 向下平移30個像素 M = np.float32([[fx, 0, 0], [0, fy, 0]]) # 進行2D 仿射變換 resized = cv2.warpAffine(img, M, (int(width*fx), int(height*fy))) cv2.imwrite('resize_raw.png', resized)
演示效果
我們利用random
模塊生成一個5×5的隨機矩陣。
# 生成一個隨機噪點 img = np.uint8(np.random.randint(0,255,size=(5,5)))
原圖
[[227 66 2 153 30] [ 8 23 68 45 91] [194 216 229 128 109] [ 73 111 189 200 111] [ 99 82 217 80 52]]
縮放后
[[227 121 44 2 101 111 30] [118 70 41 35 77 86 61] [ 8 18 38 68 53 61 91] [101 113 129 149 108 91 100] [194 208 220 229 163 121 109] [134 153 179 209 179 145 110] [ 73 98 138 189 196 169 111] [ 86 93 133 203 162 120 82] [ 99 88 128 217 127 70 52] [ 50 44 64 109 64 35 26]]
為了更加直觀的感受, 我們可以進行數據可視化。
我們使用matplotlib進行繪制 resize前與resize之后的圖片。
源代碼
src/resize_cat_v4.py
''' 仿射矩陣實現縮放 fx,fy ''' import numpy as np import cv2 from matplotlib import pyplot as plt # 生成一個隨機噪點 img = np.uint8(np.random.randint(0,255,size=(5,5))) height,width = img.shape # x軸焦距 1.5倍 fx = 1.5 # y軸焦距 2倍 fy = 2 # 聲明變換矩陣 向右平移10個像素, 向下平移30個像素 M = np.float32([[fx, 0, 0], [0, fy, 0]]) # 進行2D 仿射變換 resized = cv2.warpAffine(img, M, (int(width*fx), int(height*fy))) print(img) print(resized) # 數據可視化 plt.subplot(121) plt.imshow(img, cmap="gray") plt.subplot(122) plt.imshow(resized,cmap="gray") plt.show()