幾何變換不改變影像的像素值,只是實作影像像素點的重新安排;恰當的進行影像的幾何變換,可以減小甚至避免由于角度等一些因素造成的影像失真問題,有利于我們在識別影像時將注意力集中到影像的有效資訊中而不至于被位置、角度等因素影響
目錄
1. 平移變換
平移原理
讀取原圖資訊
構造移動矩陣
平移影像
2. 縮放變換
影像的放大
影像的縮小
3. 旋轉變換
4. 鏡像變換
復制原圖
水平鏡像
垂直鏡像
對角鏡像
5. 仿射變換
結束語
1. 平移變換
此處參考:知乎文章
平移原理
影像的平移就是將影像沿著某一個方向或者多個方向進行移動,通常會是向二維中的 x 軸或者 y 軸的方向進行移動
OpenCV 提供函式 warpAffine(img, mat, size)
各個引數含義:img -- 移動的影像
mat -- 平移矩陣,決定平移的方向和距離
size -- 決定平移后顯示影像的大小,不改變視窗大小
在進行移動時首先需要構造一個移位矩陣 mat,通過該矩陣可以確定影像的移動方向和移動距離;構造的矩陣是一個兩行三列的矩陣:
通過 x&y 來決定移動的方向以及距離
讀取原圖資訊
"""
Author:Huijun
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調整原圖大小
cv2.namedWindow("W0")
print(img1_1.shape) #讀取影像資訊
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
獲得影像:
獲得影像資訊:(487, 720, 3)
該影像為一幅解析度為 487*720 的三通道影像,當然這是經過縮放后的解析度,原解析度應該為 (487/0.6)*(720/0.6) 的三通道影像
可以試一下:
print(img1.shape) #讀取原圖資訊
獲得的資訊為:(811, 1200, 3)
構造移動矩陣
在此處需要使用到 numpy 庫
mat = np.float32([[1, 0, 0], [0, 1, 20]]) #構造平移矩陣,對 y 軸進行移動
上面的代碼是使原圖 x 軸不發生移動,y 軸移動20個單位
平移影像
"""
Author:Huijun
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調整原圖大小
cv2.namedWindow("W0")
print(img1_1.shape) #讀取影像資訊
cv2.imshow("W0", img1_1)
cv2.waitKey(delay = 0)
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #構造平移矩陣,對 y 軸進行移動
img1_1_1 = cv2.warpAffine(img1_1, mat, (487, 720))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
得到的影像如下:
首先是影像的移動距離很小(20 本來就很小),而且移動是向下的,這個和前面的文章中講到的 OpenCV 繪圖是一樣的,其次通過平移得到的影像尺寸是按照設定來的,而使用 img.shape 得到的影像資訊 x 和 y 是反過來的,下面我們對移動矩陣和移動大小進行修改:
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #構造平移矩陣,對 y 軸進行移動
img1_1_1 = cv2.warpAffine(img1_1, mat, (720, 487))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
其實移動 50 也有點小,但足夠觀察出變化
2. 縮放變換
影像的縮放就是對原圖的尺寸大小進行調整,這個我們在前面文章中已經使用過了,使用 resize() 函式就可以達到目的,在這里我們再次進行學習加強記憶
影像的放大
"""
Author:Huijun
date:2021/10/19
"""
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調整原圖大小
cv2.namedWindow("W0")
print(img1_1.shape)
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #構造平移矩陣,對 y 軸進行移動
img1_1_1 = cv2.warpAffine(img1_1, mat, (720, 487))
cv2.namedWindow("W1")
cv2.imshow("W1", img1_1_1)
cv2.waitKey(delay = 0)
img1_11 = cv2.resize(img1_1, dsize = None, fx = 2, fy = 2)
cv2.namedWindow("W2")
cv2.imshow("W2", img1_11)
cv2.waitKey(delay = 0)

在讀取原圖時已經將原圖進行了 0.6 的縮小,后面又經過了 2 倍的放大,所以最后的得到的影像應該是原圖的 1.2 倍
影像的縮小
影像的縮小其實和影像的放大一樣,只是將引數修改為小于 1 的數即可:
img1_11 = cv2.resize(img1_1, dsize = None, fx = 0.3, fy = 0.3)
0.6*0.3 = 0.18;即最上面的那幅小圖尺寸是最下面的大圖的 0.18 倍
3. 旋轉變換
此處參考:影像的幾何變換
cv2.getRotationMatrix2D()
對于影像的變換,OpenCV 提供了 getRotationMatrix2D() 函式,該函式包含三個引數,第一個引數是旋轉中心,第二個引數是旋轉角度,第三個引數是縮放比例
具體操作代碼如下:
import cv2
img1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖
img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調整原圖大小
cv2.namedWindow("W0")
print(img1_1.shape)
cv2.imshow("W0", img1)
cv2.waitKey(delay = 0)
img1_11 = cv2.resize(img1_1, dsize = None, fx = 0.3, fy = 0.3)
cv2.namedWindow("W2")
cv2.imshow("W2", img1_11)
cv2.waitKey(delay = 0)
print(img1_11.shape)
M = cv2.getRotationMatrix2D((108, 73), 45, 1) #第一個引數為旋轉中心,和上一句得到的影像資訊有關
cv2.namedWindow("W3")
res = cv2.warpAffine(img1_11, M, (216, 146))
cv2.imshow("W3", res)
cv2.waitKey(delay = 0)
可以從上面的代碼中看出,影像的旋轉最侄訓是與平移函式有關的
得到的影像如下:

但是我們可以看出旋轉后的影像顯示的不完全,如果希望通過旋轉得到完整的影像,可以參考下面的這篇文章:旋轉得到完整影像
4. 鏡像變換
所謂鏡像變換就是將影像以某一條邊或者某一條線進行對稱畫圖,其中的具體實作方法是構造一個和原圖一模一樣的影像,包括通道數,然后按照需要實作的變換將其中的像素點進行更換即可
復制原圖
我們要使用 copy.deepcopy(img) 函式進行原圖的復制
img1_2 = copy.deepcopy(img1_1)
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)

可以看出,得到的復制出的影像和原圖是一摸一樣的
水平鏡像
水平鏡像就是將影像按照左右對稱的方式進行復制,所以我們不需要改變矩陣高度方向上的像素值,只是改變水平方向上的像素點即可:
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[i, w - 1- j] = img1_1[i, j] #像素點進行更換
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)
上面顯示的就是經過水平變換得到的影像
垂直鏡像
還是和上面的水平鏡像一樣,垂直變換則是只更換高度方向的像素點即可
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[h -1 -i, j] = img1_1[i, j] #將高度方向的像素點進行更換
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)


對角鏡像
水平鏡像和垂直鏡像同時發生
img1_2 = copy.deepcopy(img1_1)
h = size[0]
w = size[1]
for i in range(h):
for j in range(w):
img1_2[h -1 -i, w - 1 - j] = img1_1[i, j]
cv2.namedWindow("W3")
cv2.imshow("W3", img1_2)
cv2.waitKey(delay = 0)

5. 仿射變換
仿射變換即為二維空間中的變換,前面提到的四種變換都可以包含在仿射變換中,如果需要加強了解可以參考下面的這篇文章,本文中就不贅述了
仿射變換(Affine Transformation)原理及應用(1)
結束語
這篇文章中總結了影像幾何變換中的平移變換、旋轉變換、縮放變換、鏡像變換、仿射變換這五個部分,后面還有透視變換單獨花一些時間來介紹,因為那部分比較難,其中參考的一些文章已經添加了鏈接,如果想進行更加全面的學習可以點進去進行查看,加油!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/328233.html
標籤:其他
上一篇:計算機發展史31-40
