簡介
在圖像進行中,平移變換、旋轉變換以及放縮變換是一些基礎且常用的操作。這些幾何變換并不改變圖象的象素值,隻是在圖象平面上進行象素的重新排列。在一幅輸入圖象 [ u , v ] [u,v] [u,v]中,灰階值僅在整數位置上有定義。然而,輸出圖象[x,y]的灰階值一般由處在非整數坐标上的 ( u , v ) (u,v) (u,v)值來決定。這就需要插值算法來進行處理,常見的插值算法有最近鄰插值、雙線性插值和三次樣條插值。
算法理論介紹與推薦
最近鄰插值算法原理
實作代碼 numpy和cv2
import numpy as np
def near_insert_1color(pic_dt, resize, x_scale=None, y_scale=None):
"""
最近鄰插值(圖檔 m * n * 圖層)
param pic_dt: 為一個圖檔的一個圖層的資料 len(pic_dt) == 2
param resize: set (長, 寬)
param x_scale: float 長度縮放大小
param y_scale: float 寬帶縮放大小
"""
m, n = pic_dt.shape
# 擷取新的圖像的大小
if resize is None:
n_new, m_new = np.round(x_scale * n).astype(int), np.round(y_scale * m).astype(int)
else:
n_new, m_new = resize
fx, fy = n / n_new, m / m_new # src_{長}/dst_{長}, src_{寬}/dst_{寬}
# 初始化X, Y的位置點
idx_x_orign = np.array(list(range(n_new)) * m_new).reshape(m_new, n_new)
idx_y_orign = np.repeat(list(range(m_new)), n_new).reshape(m_new, n_new)
# 需要的近鄰的位置
x_indx = np.round(idx_x_orign * fx).astype(int)
y_indx = np.round(idx_y_orign * fy).astype(int)
return pic_dt[y_indx, x_indx]
def near_insert(pic_dt_, resize, fx=None, fy=None):
# 三個通道分開處理再合并
if len(pic_dt_.shape) == 3:
out_img0 = near_insert_1color(pic_dt_[:,:,0], resize=resize, x_scale=fx, y_scale=fy)
out_img1 = near_insert_1color(pic_dt_[:,:,1], resize=resize, x_scale=fx, y_scale=fy)
out_img2 = near_insert_1color(pic_dt_[:,:,2], resize=resize, x_scale=fx, y_scale=fy)
out_img_all = np.c_[out_img0[:,:,np.newaxis], out_img1[:,:,np.newaxis], out_img2[:,:,np.newaxis]]
else:
out_img_all = near_insert_1color(pic_dt_, resize=resize, x_scale=fx, y_scale=fy)
return out_img_al
import cv2
"""
v2.resize(
src 【必需】原圖像
dsize 【必需】輸出圖像所需大小 (長 , 寬) (shape[1], shape[0])
fx 【可選】沿水準軸的比例因子
fy 【可選】沿垂直軸的比例因子
interpolation 【可選】插值方式
)
cv.INTER_NEAREST 最近鄰插值
cv.INTER_LINEAR 雙線性插值
cv.INTER_CUBIC 基于4x4像素鄰域的3次插值法
cv.INTER_AREA 基于局部像素的重采樣
"""
# 讀取圖檔
img = cv2.imread(pic_fil, cv2.IMREAD_UNCHANGED)
# cv2.resize 方法 放大1.5倍
resized1_5_img_near = cv2.resize(img
, dsize=None
, fx=1.5
, fy=1.5
, interpolation=cv2.INTER_NEAREST)
# 用自己寫的函數實作近鄰插值
out_img_all = near_insert(img, resize=None, fx=1.5, fy=1.5)
缺點: 用該方法作放大處理時,在圖象中可能出現明顯的塊狀效應
雙線性插值算法
線性插值多項式:
雙線性插值就是線性插值在二維時的推廣,在兩個方向上做三次線性插值,具體操作如下圖所示:
映射方法
向前映射法
可以将幾何運算想象成一次一個象素地轉移到輸出圖像中。如果一個輸入象素被映射到四個輸出像素之間的位置,則其灰階值就按插值算法在4個輸出象素之間進行配置設定。稱為向前映射法,或象素移交影射。 注:從原圖象坐标計算出目标圖象坐标鏡像、平移變換使用這種計算方法
向後映射法
向後映射法(或象素填充算法)是輸出象素一次一個地映射回到輸入象素中,以便确定其灰階級。如果一個輸出象素被映射到4個輸入象素之間,則其灰階值插值決定,向後空間變換是向前變換的逆。
注:從結果圖象的坐标計算原圖象的坐标
旋轉、拉伸、放縮可以使用
解決了漏點的問題,出現了馬賽克
實作
通常,縮小使用cv.INTER_AREA,放縮使用cv.INTER_CUBIC(較慢)和cv.INTER_LINEAR(較快效果也不錯)。預設情況下,所有的放縮都使用cv.INTER_LINEAR。
import cv2
if __name__ == "__main__":
img = cv2.imread('D:/image/yuner.jpg', cv2.IMREAD_UNCHANGED)
print('Original Dimensions : ',img.shape)
scale_percent = 30 # percent of original size
width = int(img.shape[1] * scale_percent / 100)
height = int(img.shape[0] * scale_percent / 100)
dim = (width, height)
# resize image
resized = cv2.resize(img, dim, interpolation = cv2.INTER_LINEAR)
fx = 1.5
fy = 1.5
resized1 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_NEAREST)
resized2 = cv2.resize(resized, dsize=None, fx=fx, fy=fy, interpolation = cv2.INTER_LINEAR)
print('Resized Dimensions : ',resized.shape)
cv2.imshow("Resized image", resized)
cv2.imshow("INTER_NEAREST image", resized1)
cv2.imshow("INTER_LINEAR image", resized2)
cv2.waitKey(0)
cv2.destroyAllWindows()