Python 计算机视觉(五)—— OpenCV 进行图像几何变换
? ? ? ?幾何變換不改變圖像的像素值,只是實現(xiàn)圖像像素點的重新安排;恰當(dāng)?shù)倪M行圖像的幾何變換,可以減小甚至避免由于角度等一些因素造成的圖像失真問題,有利于我們在識別圖像時將注意力集中到圖像的有效信息中而不至于被位置、角度等因素影響
目錄
1. 平移變換
平移原理
讀取原圖信息
構(gòu)造移動矩陣
平移圖像
2. 縮放變換
圖像的放大
圖像的縮小
3. 旋轉(zhuǎn)變換
4. 鏡像變換
復(fù)制原圖
水平鏡像
垂直鏡像
對角鏡像
5. 仿射變換
結(jié)束語
1. 平移變換
此處參考:知乎文章
平移原理
? ? ? ?圖像的平移就是將圖像沿著某一個方向或者多個方向進行移動,通常會是向二維中的 x 軸或者 y 軸的方向進行移動
? ? ? ?OpenCV 提供函數(shù) warpAffine(img, mat, size)
各個參數(shù)含義:img?-- 移動的圖像
mat -- 平移矩陣,決定平移的方向和距離
size -- 決定平移后顯示圖像的大小,不改變窗口大小
? ? ? 在進行移動時首先需要構(gòu)造一個移位矩陣 mat,通過該矩陣可以確定圖像的移動方向和移動距離;構(gòu)造的矩陣是一個兩行三列的矩陣:
? ? ?通過 x&y 來決定移動的方向以及距離
讀取原圖信息
""" Author:XiaoMa date:2021/10/19 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖 img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調(diào)整原圖大小 cv2.namedWindow("W0") print(img1_1.shape) #讀取圖像信息 cv2.imshow("W0", img1) cv2.waitKey(delay = 0)獲得圖像:
獲得圖像信息:(487, 720, 3)
該圖像為一幅分辨率為 487*720?的三通道圖像,當(dāng)然這是經(jīng)過縮放后的分辨率,原分辨率應(yīng)該為 (487/0.6)*(720/0.6) 的三通道圖像
可以試一下:
print(img1.shape) #讀取原圖信息獲得的信息為:(811, 1200, 3)?
構(gòu)造移動矩陣
在此處需要使用到 numpy 庫
mat = np.float32([[1, 0, 0], [0, 1, 20]]) #構(gòu)造平移矩陣,對 y 軸進行移動上面的代碼是使原圖 x 軸不發(fā)生移動,y 軸移動20個單位
平移圖像
""" Author:XiaoMa date:2021/10/19 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖 img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調(diào)整原圖大小 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]]) #構(gòu)造平移矩陣,對 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 繪圖是一樣的,其次通過平移得到的圖像尺寸是按照設(shè)定來的,而使用 img.shape 得到的圖像信息 x 和 y 是反過來的,下面我們對移動矩陣和移動大小進行修改:
mat = np.float32([[1, 0, 0], [0, 1, 50]]) #構(gòu)造平移矩陣,對 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. 縮放變換
? ? ? ? ?圖像的縮放就是對原圖的尺寸大小進行調(diào)整,這個我們在前面文章中已經(jīng)使用過了,使用 resize() 函數(shù)就可以達(dá)到目的,在這里我們再次進行學(xué)習(xí)加強記憶
圖像的放大
""" Author:XiaoMa date:2021/10/19 """ import cv2 import numpy as np import matplotlib.pyplot as pltimg1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖 img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調(diào)整原圖大小 cv2.namedWindow("W0") print(img1_1.shape) cv2.imshow("W0", img1) cv2.waitKey(delay = 0)mat = np.float32([[1, 0, 0], [0, 1, 50]]) #構(gòu)造平移矩陣,對 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)? ? ? ?在讀取原圖時已經(jīng)將原圖進行了 0.6 的縮小,后面又經(jīng)過了 2 倍的放大,所以最后的得到的圖像應(yīng)該是原圖的 1.2 倍
圖像的縮小
? ? ? ?圖像的縮小其實和圖像的放大一樣,只是將參數(shù)修改為小于 1 的數(shù)即可:
img1_11 = cv2.resize(img1_1, dsize = None, fx = 0.3, fy = 0.3)? ? ? ? ?0.6*0.3 = 0.18;即最上面的那幅小圖尺寸是最下面的大圖的 0.18 倍?
3. 旋轉(zhuǎn)變換
此處參考:圖像的幾何變換
cv2.getRotationMatrix2D()
? ? ? ?對于圖像的變換,OpenCV 提供了?getRotationMatrix2D() 函數(shù),該函數(shù)包含三個參數(shù),第一個參數(shù)是旋轉(zhuǎn)中心,第二個參數(shù)是旋轉(zhuǎn)角度,第三個參數(shù)是縮放比例
具體操作代碼如下:
import cv2img1 = cv2.imread('E:\From Zhihu\For the desk\de.jpg') #讀取原圖 img1_1 = cv2.resize(img1, dsize = None, fx = 0.6, fy = 0.6) #調(diào)整原圖大小 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) #第一個參數(shù)為旋轉(zhuǎn)中心,和上一句得到的圖像信息有關(guān) cv2.namedWindow("W3") res = cv2.warpAffine(img1_11, M, (216, 146))cv2.imshow("W3", res) cv2.waitKey(delay = 0)? ? ? ? 可以從上面的代碼中看出,圖像的旋轉(zhuǎn)最終還是與平移函數(shù)有關(guān)的
得到的圖像如下:
? ??? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
但是我們可以看出旋轉(zhuǎn)后的圖像顯示的不完全,如果希望通過旋轉(zhuǎn)得到完整的圖像,可以參考下面的這篇文章:旋轉(zhuǎn)得到完整圖像?
4. 鏡像變換
? ? ? ?所謂鏡像變換就是將圖像以某一條邊或者某一條線進行對稱畫圖,其中的具體實現(xiàn)方法是構(gòu)造一個和原圖一模一樣的圖像,包括通道數(shù),然后按照需要實現(xiàn)的變換將其中的像素點進行更換即可
復(fù)制原圖
? ? ? ?我們要使用 copy.deepcopy(img) 函數(shù)進行原圖的復(fù)制
img1_2 = copy.deepcopy(img1_1) cv2.namedWindow("W3") cv2.imshow("W3", img1_2) cv2.waitKey(delay = 0)? ? ? ?可以看出,得到的復(fù)制出的圖像和原圖是一摸一樣的
水平鏡像
? ? ? ?水平鏡像就是將圖像按照左右對稱的方式進行復(fù)制,所以我們不需要改變矩陣高度方向上的像素值,只是改變水平方向上的像素點即可:
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)?? ? ? ?上面顯示的就是經(jīng)過水平變換得到的圖像?
垂直鏡像
? ? ? ?還是和上面的水平鏡像一樣,垂直變換則是只更換高度方向的像素點即可
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)對角鏡像
? ? ? ? 水平鏡像和垂直鏡像同時發(fā)生
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)原理及應(yīng)用(1)
結(jié)束語
? ? ? 這篇文章中總結(jié)了圖像幾何變換中的平移變換、旋轉(zhuǎn)變換、縮放變換、鏡像變換、仿射變換這五個部分,后面還有透視變換單獨花一些時間來介紹,因為那部分比較難,其中參考的一些文章已經(jīng)添加了鏈接,如果想進行更加全面的學(xué)習(xí)可以點進去進行查看,加油!
總結(jié)
以上是生活随笔為你收集整理的Python 计算机视觉(五)—— OpenCV 进行图像几何变换的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python 计算机视觉(四)—— Op
- 下一篇: Python 计算机视觉(六)—— Op