遇到了一些情況需要將圖片旋轉一定角度使其相對來說是符合人類認知的形式【就是歪圖轉正】於是接觸了處理圖片的經典方式——仿射變換
定義:仿射變換的功能是從二維坐標到二維坐標之間的線性變換,且保持二維圖形的“平直性”和“平行性”。仿射變換可以通過一系列的原子變換的復合來實現,包括平移,縮放,翻轉,旋轉和剪切。
1)圖像的幾何變換
對圖像進行放大、縮小、旋轉等操作,會改變原圖中各區域的空間關系,這類操作就是圖像的幾何變換。
2)仿射變換
對原來的x和y坐標分別進行線性的幾何變換,得到新的x和y,這種變換就是放射變換。
3)投影變換
4)極坐標變換
5)齊次坐標
在原坐標的基礎上,引入第三個數值為1的坐標,這種表示方法就是齊次坐標。
6)仿射變換矩陣
仿射變換矩陣的最后一行均為(0,0,1)此形式,最后一個值為1。
平移(translation)和旋轉(rotation) 顧名思義,兩者的組合稱之為 歐式變換(Euclidean transformation) 或 剛體變換(rigid transformation);
放縮(scaling) 可進一步分為 uniform scaling和non-uniform scaling,前者每個坐標軸放縮系數相同(各向同性),后者不同;如果放縮系數為負,則會疊加上反射(reflection)——可以看成是特殊的scaling;
剛體變換+uniform scaling 稱之為,相似變換(similarity transformation),即平移+旋轉+各向同性的放縮;
剪切變換(shear mapping) 將所有點沿某一指定方向成比例地平移
上圖
這張圖就是被各大博客,知乎精華所引用的仿射變換的
簡單來說,圖像的本質可以看做一個三維矩陣,第一維為長度,第二維是寬度,第三維是通道數(RGB),如果一張圖在python中是一個變量image,那么其長寬即width, height = image.shape[:2],即前兩維度的表示方法。
對於圖像矩陣中的每一個像素坐標(x,y),我們可以令其乘上一個矩陣,使所有像素坐標平移,旋轉,縮放,翻轉到處理后的圖像新坐標上
對於每種操作的矩陣構造如下:
以下是對單一變換時所做的矩陣操作
要知道,計算機中往往左上角是坐標原點,圖片的高度(width)是X軸,寬度(height)是Y軸,因此當以原點為圓心順時針旋轉90°為例,我們將把圖旋轉出第一象限,此時需要將圖片向Y軸方向平移原圖的高度(width)才能回到第一象限:
這樣的復合操作其實是多個矩陣相乘的結果
分解后是多個單獨的操作
以(0,0)為中心進行放大和縮小
這里的放大和縮小不是指在物理空間中某一物體的放大和縮小。
二維空間坐標(x, y)以(0,0)為中心,在水平上縮放Sx倍,指的是變換后的坐標位置(x’,y’)離(0,0)的水平距離變為原坐標(x,y)離位置中心點的水平距離的Sx倍;在垂直方向上縮放Sy倍,指的是變換后的坐標位置(x’,y’)離(0,0)的垂直距離為原坐標(x,y)離位置中心的垂直距離的Sy倍。
用數學公式表示,(x’, 'y) = (Sx * x, Sy * y)
如果Sx>1,則表示在水平方向上放大;如果0<Sx<1,則表示在水平方向上縮小。
如果Sy>1,則表示在垂直方向上放大;如果0<Sy<1,則表示在垂直方向上縮小。
假設已知參數是圖片本體,我們可以自己構造一個需要的仿射變換矩陣,做自定義操作。
如順時針旋轉90°:
width, height = img.shape[:2]
transform = np.matrix(
[[1, 0, 0], [0, 1, width], [0, 0, 1]], dtype='float')
transform *= np.matrix(
[
[np.cos(np.pi / 2), np.sin(np.pi / 2), 0],
[-np.sin(np.pi / 2), np.cos(np.pi / 2), 0], [0, 0, 1]
],
dtype='float')
transform = np.linalg.inv(transform)
img = cv2.warpAffine(img, transform[:2], (width, height))
以(x0,y0)為中心的放大和縮小
以(0,0)為中心的放大和縮小,很容易理解。而以(x0,y0)為中心的放大和縮小,直接來理解比較苦難。但是可以用分解步驟的思想來進行理解,可以變得簡單一些。
以(x0,y0)為中心的縮放(x,y)=先將原點(0,0)移動到中心點(x0,y0)—>以新原點為中心點進行縮放—>然后再移回坐標原點。
等比例縮放
在上面放大和縮小的公式中,如果Sx==Sy,則表示是等比例縮放。
吐槽一下自己,突然意識到自己從秋招回學校之后就開始浪了,再也懶得寫博客了,雖然零零散散接觸了些新東西,但是沒有系統的學過,也不好將皮毛整理成博客。接下來是正經的學習期,以及畢設的准備與實踐采坑,,,新的開始,忘掉過去,要寫一些更實用的博客了。