您好,登錄后才能下訂單哦!
這篇文章主要介紹了OpenCV+Python如何實現(xiàn)幾何變換,具有一定借鑒價值,感興趣的朋友可以參考下,希望大家閱讀完這篇文章之后大有收獲,下面讓小編帶著大家一起了解一下。
圖像的幾何變換是指將一幅圖像映射到另一幅圖像內(nèi)。有縮放、翻轉(zhuǎn)、仿射變換、透視、重映射等操作。
使用cv2.resize()函數(shù)實現(xiàn)對圖像的縮放,但要注意cv2.resize()函數(shù)內(nèi)的dsize參數(shù)與原圖像的行列屬性是相反的,也就是:目標(biāo)圖像的行數(shù)是原始圖像的列數(shù),目標(biāo)圖像的列數(shù)是原始圖像的行數(shù)。
下面舉例說明cv2.resize()函數(shù)的用法:
import cv2 img=cv2.imread('E:/python_opencv/tupian.jpg') rows,cols=img.shape[0:2] #行數(shù)和列數(shù)等于img的長度和寬度 size=(int(cols*0.9),int(rows*0.5)) #比例:列變?yōu)樵瓉?.9倍,行變?yōu)?.5倍 rst=cv2.resize(img,size) #將img按size比例縮放 print('img.shape=',img.shape) print('rst.shape=',rst.shape)
運行程序的結(jié)果如下:
img.shape=(600,60,3)
rst.shape=(300,54,3)
可以看出,行數(shù)變?yōu)樵瓉淼?.5倍,列數(shù)變?yōu)樵瓉淼?.9倍。代碼中size的行列位置發(fā)生了交換。
使用cv2.flip()函數(shù)對圖像翻轉(zhuǎn),能夠?qū)崿F(xiàn)水平方向翻轉(zhuǎn)、垂直方向翻轉(zhuǎn)、兩個方向同時翻轉(zhuǎn)。
下面舉例說明cv2.flip()函數(shù)的用法:
import cv2 img=cv2.imread('E:/python_opencv/tupian.jpg') x=cv2.flip(img,0) #圖x對原圖像繞x軸翻轉(zhuǎn) y=cv2.flip(img,1) #圖y對原圖像繞y軸翻轉(zhuǎn) xy=cv2.flip(img,-1) #圖xy對原圖像繞x軸y軸同時翻轉(zhuǎn) cv2.imshow('img',img) cv2.imshow('x',x) cv2.imshow('y',y) cv2.imshow('xy',xy) cv2.waitKey() cv2.destroyAllWindows()
程序運行結(jié)果如下四幅圖,第一幅是原圖,第二幅是繞x軸翻轉(zhuǎn),第三幅是繞y軸翻轉(zhuǎn),第四幅是繞x軸y軸同時翻轉(zhuǎn)。
仿射變換是指圖像實現(xiàn)平移、旋轉(zhuǎn)等操作。
先設(shè)置一個變換矩陣M,然后使用cv2.warpAffine()函數(shù)對原圖像和變換矩陣M進行仿射操作。
要實現(xiàn)圖像的平移,我們先自定義一個轉(zhuǎn)換矩陣,再進行仿射平移變換。例程如下:
import cv2 import numpy as np img=cv2.imread('E:\python_opencv/tupian.jpg') height,width=img.shape[:2] #讀取原圖像的長和寬 x=100 #自定義轉(zhuǎn)換矩陣M的x軸移動值 y=200 #自定義轉(zhuǎn)換矩陣M的y軸移動值 M=np.float32([[1,0,x],[0,1,y]]) #構(gòu)造轉(zhuǎn)換矩陣M move=cv2.warpAffine(img,M,(width,height)) #平移映射 cv2.imshow('orginal',img) cv2.imshow('move',move) cv2.waitKey() cv2.destroyAllWindows()
程序運行結(jié)果如下圖所示,左為原圖,右為平移后的圖。
使用函數(shù)cv2.getRotationMatrix2D()獲得轉(zhuǎn)移矩陣M,然后使用函數(shù)cv2.warpAffine()進行仿射旋轉(zhuǎn)變換。例程如下:
import cv2 img=cv2.imread('E:\python_opencv/tupian.jpg') height,width=img.shape[:2] #讀取原圖像的長和寬 M=cv2.getRotationMatrix2D((width/2,height/2),45,0.6) #以中心為原點,逆時針旋轉(zhuǎn)45°,且縮小為原圖的0.6倍,獲得轉(zhuǎn)移矩陣M rotate=cv2.warpAffine(img,M,(width,height)) #旋轉(zhuǎn)映射 cv2.imshow('original',img) cv2.imshow('rotation',rotate) cv2.waitKey() cv2.destroyAllWindows()
程序運行結(jié)果如下圖所示,左為原圖,右為旋轉(zhuǎn)后的圖。
透視變換是指將矩陣圖形投影到另一個視平面,可以映射為任意四邊形,所以透視變換也被稱為投影映射(ProjectionMapping),并不是字面意義上的“透視”。透視與上節(jié)的仿射不同,仿射可以將矩陣映射為任意平行四邊形。
使用cv2.warpPerspective()函數(shù)實現(xiàn)透視變換。例程如下:
#完成圖像透視 import cv2 import numpy as np img=cv2.imread('E:/python_opencv/tupian.jpg') rows,cols=img.shape[:2] #讀取原圖像的長和寬 print(rows,cols) #生成旋轉(zhuǎn)矩陣M pts1=np.float32([[150,50],[400,50],[60,450],[310,450]]) pts2=np.float32([[50,50],[rows-50,50],[50,cols-50],[rows-50,cols-50]]) M=cv2.getPerspectiveTransform(pts1,pts2) #使用函數(shù)cv2.warpPerspective()進行透視變換 dst=cv2.warpPerspective(img,M,(cols,rows)) cv2.imshow('img',img) cv2.imshow('dst',dst) cv2.waitKey() cv2.destroyAllWindows()
程序運行結(jié)果如下圖所示,左為原圖,右為透視變換的圖。
我們可以看到,原圖片經(jīng)過透視映射后,變成另一個視角下的任意四邊形了。
重映射是修改了像素點的位置,從而生成一幅新的圖像,包括:復(fù)制、繞x軸y軸翻轉(zhuǎn),x軸y軸互換,圖像縮放等。
均使用cv2.remap()重映射函數(shù)進行操作。
需要注意cv2.remap()中的兩個參數(shù)mapx、mapy。mapx表示對應(yīng)位置上x軸坐標(biāo)值,mapy表示對應(yīng)位置上y軸坐標(biāo)值。
使用cv2.remap()函數(shù)完成圖像復(fù)制,需先定義mapx,mapy的值,然后循環(huán)映射每個像素點到對應(yīng)的位置上。
代碼如下:
import cv2 import numpy as np img=cv2.imread('E:/python_opencv/tupian.jpg') rows,cols=img.shape[:2] #讀取行列數(shù) mapx=np.zeros(img.shape[:2],np.float32) #mapx參數(shù)設(shè)定為對應(yīng)位置上的x軸坐標(biāo)值 mapy=np.zeros(img.shape[:2],np.float32) #mapy參數(shù)設(shè)定為對應(yīng)位置上的y軸坐標(biāo)值 for i in range(rows): #對每個元素復(fù)制映射 for j in range(cols): mapx.itemset((i,j),j) mapy.itemset((i,j),i) rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) cv2.imshow('original',img) cv2.imshow('result',rst) cv2.waitKey() cv2.destroyAllWindows()
執(zhí)行后結(jié)果如下所示,可以看到,實現(xiàn)了圖像的復(fù)制重映射。
重映射法對圖像繞x軸翻轉(zhuǎn),表明mapx的值保持不變,mapy的值調(diào)整為總行數(shù)-1-當(dāng)前行號,其余部分代碼不變,所以循環(huán)體內(nèi)代碼變?yōu)椋?/p>
for i in range(rows): for j in range(cols): mapx.itemset((i,j),j) #mapx的值保持不變 mapy.itemset((i,j),rows-1-i) #mapy的值調(diào)整為總行數(shù)-1-當(dāng)前行號
重映射法對圖像繞y軸翻轉(zhuǎn),表明mapx的值調(diào)整為總行數(shù)-1-當(dāng)前列號,mapy的值保持不變,所以循環(huán)體內(nèi)代碼變?yōu)椋?/p>
for i in range(rows): for j in range(cols): mapx.itemset((i,j),cols-1-j) #mapx的值調(diào)整為總列數(shù)-1-當(dāng)前列號 mapy.itemset((i,j),i) #mapy的值保持不變
重映射也能實現(xiàn)圖像繞x軸和y軸的同時翻轉(zhuǎn),只需將前兩個部分合并,使mapx的值調(diào)整為總行數(shù)-1-當(dāng)前列號,mapy的值調(diào)整為總行數(shù)-1-當(dāng)前行號。例程如下:
import cv2 import numpy as np img=cv2.imread('E:\python_opencv/tupian.jpg') rows,cols=img.shape[:2] mapx=np.zeros(img.shape[:2],np.float32) mapy=np.zeros(img.shape[:2],np.float32) for i in range(rows): for j in range(cols): mapx.itemset((i,j),cols-1-j) #mapx的值調(diào)整為總列數(shù)-1-當(dāng)前列號 mapy.itemset((i,j),rows-1-i) #mapy的值調(diào)整為總行數(shù)-1-當(dāng)前行號 rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) cv2.imshow('original',img) cv2.imshow('result',rst) cv2.waitKey() cv2.destroyAllWindows()
執(zhí)行后結(jié)果如下所示,可以看到,實現(xiàn)了圖像的繞x軸和y軸翻轉(zhuǎn)重映射過程。
重映射中,x軸、y軸互換表明,mapx的值變?yōu)樗谛械男刑枺琺apy的值變?yōu)樗诹械牧刑枴?/p>
但當(dāng)行數(shù)和列數(shù)不一致時,行或列無法完成映射的部分就被處理為0。示例代碼如下:
#使用函數(shù)cv2.remap()實現(xiàn)圖像繞x軸和y軸的互換 import cv2 import numpy as np img=cv2.imread('E:\python_opencv/tupian.jpg') rows,cols=img.shape[:2] mapx=np.zeros(img.shape[:2],np.float32) mapy=np.zeros(img.shape[:2],np.float32) for i in range(rows): for j in range(cols): mapx.itemset((i,j),i) #mapx的值變?yōu)樗谛械男刑? mapy.itemset((i,j),j) #mapy的值變?yōu)樗诹械牧刑? rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) cv2.imshow('original',img) cv2.imshow('result',rst) cv2.waitKey() cv2.destroyAllWindows()
結(jié)果如圖:
可以看到,列數(shù)多于行數(shù)的部分被置為0(黑色)。
重映射提供了cv2.remap()函數(shù)能夠?qū)崿F(xiàn)圖像的放大或縮小。處理圖像后,可以將圖像固定在圍繞其中心的某個區(qū)域。
下面例程中,x軸和y軸均縮小為原來的0.25-0.75倍之間。
import cv2 import numpy as np img=cv2.imread('E:\python_opencv/tupian.jpg') rows,cols=img.shape[:2] mapx=np.zeros(img.shape[:2],np.float32) mapy=np.zeros(img.shape[:2],np.float32) for i in range(rows): for j in range(cols): if 0.25*cols < i < 0.75*cols and 0.25*rows < i < 0.75*rows: #在目標(biāo)圖像的x軸(0.25-0.75)倍之內(nèi)生成縮小圖像 mapx.itemset((i,j),2*(j-0.25*cols)+0.5) #在目標(biāo)圖像的y軸(0.25-0.75)倍之內(nèi)生成縮小圖像 mapy.itemset((i,j),2*(i-rows*0.25)+0.5) else: #不在上述區(qū)域的點都取(0,0)坐標(biāo)點的值 mapx.itemset((i,j),0) mapy.itemset((i,j),0) rst=cv2.remap(img,mapx,mapy,cv2.INTER_LINEAR) #圖像縮放重映射 cv2.imshow('original',img) cv2.imshow('result',rst) cv2.waitKey() cv2.destroyAllWindows()
感謝你能夠認(rèn)真閱讀完這篇文章,希望小編分享的“OpenCV+Python如何實現(xiàn)幾何變換”這篇文章對大家有幫助,同時也希望大家多多支持億速云,關(guān)注億速云行業(yè)資訊頻道,更多相關(guān)知識等著你來學(xué)習(xí)!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。