??寫在前面??
??個(gè)人主頁(yè):https://blog.csdn.net/m0_52051577?type=blog?
??歡迎各位大佬支持點(diǎn)贊收藏,三連必回?。?/p>
??本人新開(kāi)系列專欄—python圖像處理
?愿每一個(gè)驟雨初晴之時(shí),所有的蜻蜓振翅和雨后驚雷,都?xì)w你。
前言
? ? ? 圖像幾何變換就是在不改變圖像像素值的前提下,對(duì)圖像進(jìn)行像素變換的處理。通常幾何變換可以用來(lái)解決由成像的角度、透視位置不合預(yù)期等問(wèn)題。比如拍攝的斜著的路牌,如果我們?cè)谥荒軐?duì)現(xiàn)有的照片進(jìn)行處理的情況下又想要從側(cè)面看到路牌上的字體,那么此時(shí)就要用到幾何變換。
? ? ? 幾何變換作為圖像歸一化的核心工作之一,對(duì)圖像的預(yù)處理起到了重要作用。?
目錄
一、所需函數(shù)及基礎(chǔ)變換的插值方法
1.所需函數(shù)
2.常見(jiàn)插值方法
3.最近鄰插值
4.最近鄰和雙線性插值比較
二、圖像操作
1.裁剪圖像 (放大縮?。?/p>
? ? ? ???2.平移變換?
? ? ? ? ?3.錯(cuò)切變換?
? ? ? ? ?4.鏡像變換
4.1方式一
4.2方式二
? ? ? ? ??5.旋轉(zhuǎn)變換?
5.1方式一
5.2方式二
5.3設(shè)置不同縮放因子時(shí)的旋轉(zhuǎn)效果
?6.放大縮小
?7.透視變換
?注:本文涉及到的圖片資源可在博客積分資源中獲取,相關(guān)鏈接:https://download.csdn.net/download/m0_52051577/87844285?spm=1001.2014.3001.5503?
一、所需函數(shù)及基礎(chǔ)變換的插值方法
1.所需函數(shù)
cv.resize(src, dsize,dst=None,fx=None, fy=None, interpolation=None)
功能:用來(lái)放大及縮小圖像的函數(shù)。
參數(shù):[輸入圖像,修改尺寸,輸出圖像,x方向縮放系數(shù),Y 方向縮放系數(shù),插值方式]
M = np.array([[...]], dtype=np.float32)
cv.warpAffine(img, M, dsize)功能:對(duì)圖像進(jìn)行平移變換。
參數(shù):M表示構(gòu)造的變換矩陣,warpAffine()函數(shù)中img表示變換的圖像,M表示變換矩陣,dsize設(shè)置修改尺寸。
cv.flip(img,bool)
功能:對(duì)圖像進(jìn)行鏡像變換。
參數(shù):其中img表示變換的圖像,flip()函數(shù)中bool為布爾值,可選0或1,0表示垂直鏡像;1表示水平鏡像;-1表示水平垂直同時(shí)進(jìn)行。
M = cv.getRotationMatrix2D(center, angle, scale)
功能:對(duì)圖像進(jìn)行旋轉(zhuǎn)變換(角度可定義)
參數(shù):
getRotationMatrix2D()函數(shù)中center 表示旋轉(zhuǎn)圖像所要圍繞的中心點(diǎn)。
angle 表示旋轉(zhuǎn)的角度. 在OpenCV中正角度是逆時(shí)針的。
scale 表示縮放因子,可選的。
img_rotate = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)
功能:對(duì)圖像進(jìn)行旋轉(zhuǎn)變換(90°)
參數(shù):rotate()旋轉(zhuǎn)函數(shù),將圖像旋轉(zhuǎn)90°。
M = cv.getPerspectiveTransform(src, dst)
功能:求得圖像透視變換的變換矩陣。
參數(shù):cv2.getPerspectiveTransform()函數(shù)根據(jù)圖像中不共線的 4 個(gè)點(diǎn)在變換前后的對(duì)應(yīng)位置求得 (3x3) 變換矩陣。
img = cv.warpPerspective(img, M, dsize)
功能:對(duì)圖像進(jìn)行透視變換。
參數(shù):cv2.warpPerspective?使用該 (3x3) 變換矩陣即可求出變換后的圖像。標(biāo)量進(jìn)行加法運(yùn)算。?
2.常見(jiàn)插值方法
在做圖像處理時(shí),經(jīng)常會(huì)碰到小數(shù)像素坐標(biāo)的取值問(wèn)題,這就需要一種插值算法來(lái)對(duì)坐標(biāo)進(jìn)行插值。常見(jiàn)的四種插值方法如下:
最近鄰插值: interpolation = cv.INTER_NEAREST
放大圖片:interpolation = cv.INTER_CUBIC(速度慢)
? ? ? ? ? ? ? ? ? interpolation = cv.INTER_LINEAR ?線性插值(速度快)
縮小圖片:interpolation = cv.INTER_AREA
3.最近鄰插值
將原本10X10的圖像放大成15X15,放大1.5倍。
比如要計(jì)算新圖像在(10,11)處的灰度值,則對(duì)應(yīng)原圖像(10/1.5,11/1.5)= (6.7,7.3)處的灰度值,四舍五入取整,選取原圖像(7,7)處的灰度值即可。如下圖:
4.最近鄰和雙線性插值比較
##### 最近鄰和雙線性插值比較
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
plt.imshow(cv.cvtColor(img, cv.COLOR_BGR2RGB), cmap='gray', vmin=0, vmax=255)
plt.show()
img = cv.imread('pic/rabbit50x33.jpg')
img_resize1 = cv.resize(img, (330, 500), interpolation=cv.INTER_NEAREST)
img_resize2 = cv.resize(img, (330, 500), interpolation=cv.INTER_LINEAR)
show(img)
show(np.hstack([img_resize1, img_resize2]))
?
最左圖為模糊處理后的圖像,中間圖為最近鄰處理的效果圖,最右圖為雙插值處理的效果圖,可見(jiàn)同樣圖片尺寸下,雙插值處理效果更清晰。
二、圖像操作
首先,定義導(dǎo)入圖片的函數(shù)。
import cv2 as cv
import numpy as np
import matplotlib.pyplot as plt
def show(img):
if img.ndim == 2:
plt.imshow(img, cmap='gray', vmin=0, vmax=255)
else:
img = cv.cvtColor(img, cv.COLOR_BGR2RGB)
plt.imshow(img)
plt.show()
1.裁剪圖像 (放大縮?。?/h3>
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
img.shape #查看圖像維度
img = cv.imread('pic/rabbit500x333.jpg')
show(img)
img.shape #查看圖像維度
?如圖,原圖的維度為(500,333,3),下面將圖像裁剪。
# 裁剪
rabbit = img[150:450, 50:300, :]
show(rabbit)
?
如圖,裁剪后的維度中,150:450表示縱軸上裁剪的長(zhǎng)度,50:300表示橫軸上裁剪的長(zhǎng)度。?
?2.平移變換?
平移變換的原理為,在原有像素點(diǎn)的基礎(chǔ)上指定x方向與y方向的偏移量▲x與▲y,將原有的像素坐標(biāo)(x0,y0)進(jìn)行處理,平移后的坐標(biāo)為(x,y);并將方程寫成原向量與偏移向量相加的形式。同時(shí)原向量還可寫成[[1,0],[0,1]]向量組與[x0,y0]相乘的形式,隨后再偏移向量填補(bǔ),寫成3階矩陣與3維向量相乘的形式,從而實(shí)現(xiàn)平移變換。
# 平移
transM = np.array([
[1, 0, 20],
[0, 1, 100]
], dtype=np.float32)
img_trans = cv.warpAffine(img, transM, dsize=(333, 500))
show(img_trans)
?
如圖,首先構(gòu)造平移矩陣transM,?分別指定x與y方向上的平移量,用圖像中每個(gè)像素點(diǎn)對(duì)應(yīng)的矩陣點(diǎn)乘平移矩陣transM,從而實(shí)現(xiàn)圖像的平移變換。其中dsize是設(shè)置平移圖像的尺寸。
3.錯(cuò)切變換?
錯(cuò)切變換實(shí)現(xiàn)原理:令x=x0+y0tanθ,y=y0。按上圖公式進(jìn)行變換,y0tanθ為x在水平方向上的錯(cuò)切量,縱軸位置不變,從而實(shí)現(xiàn)水平方向的錯(cuò)切變換。
# 錯(cuò)切
shearM = np.array([
[1, 0.3, 0],
[0, 1, 0]
], dtype=np.float32)
img_shear = cv.warpAffine(img, shearM, dsize=(400, 500))
show(img_shear)
?
如圖,錯(cuò)切變換后的圖像是由矩陣錯(cuò)切變換公式得來(lái)的,公式中tanα表示橫坐標(biāo)錯(cuò)切比例,橫坐標(biāo)錯(cuò)切量dx=原像素點(diǎn)縱坐標(biāo)y0×錯(cuò)切所占比例tanα。同理,tanβ表示縱坐標(biāo)錯(cuò)切比例,縱坐標(biāo)錯(cuò)切量dy=原像素點(diǎn)縱坐標(biāo)x0×錯(cuò)切所占比例tanβ。以這樣的方式得到的圖像即為錯(cuò)切變換圖像。?
4.鏡像變換
?鏡像變換原理:本質(zhì)是將水平或豎直方向的坐標(biāo)對(duì)稱過(guò)去。
4.1方式一
# 鏡像1
mirrorM = np.array([
[-1, 0, 333],
[0, 1, 0]
], dtype=np.float32)
img_mirr = cv.warpAffine(img, mirrorM, dsize=img.shape[:2][::-1])
show(img_mirr)
?
如圖,mirrorM中,x方向向量的首位元素為-1,表示將原圖橫向翻轉(zhuǎn),縱軸不變。?
?4.2方式二
# 鏡像2
img_mirh = cv.flip(img, 1)
img_mirv = cv.flip(img, 0)
img_mirb = cv.flip(img, -1)
show(np.hstack([img, img_mirh, img_mirv, img_mirb]))
?
如圖,采用flip()函數(shù)進(jìn)行鏡像翻轉(zhuǎn),其中1表示水平翻轉(zhuǎn),0表示豎直翻轉(zhuǎn),-1表示水平豎直同時(shí)進(jìn)行。
5.旋轉(zhuǎn)變換?
?旋轉(zhuǎn)變換原理:首先定義旋轉(zhuǎn)矩陣,再將原圖像對(duì)應(yīng)向量×矩陣中每個(gè)行向量分量。
?
旋轉(zhuǎn)矩陣推導(dǎo)過(guò)程如上圖,定義旋轉(zhuǎn)半徑r,旋轉(zhuǎn)角α和β,其中(x0,y0)根據(jù)三角公式可以用r和α表示出來(lái)。
那么同理,要想將(x0,y0)變換到新坐標(biāo)(x,y),同樣用r和旋轉(zhuǎn)角來(lái)表示,此時(shí)的旋轉(zhuǎn)角為α-β,表示出新坐標(biāo)(x,y)后,再用rcosα和rsinα替換掉x0,y0。并將方程組寫成矩陣相乘的形式,即為旋轉(zhuǎn)矩陣。
5.1方式一
# 旋轉(zhuǎn)1
img_rotate = cv.rotate(img, cv.ROTATE_90_CLOCKWISE)
show(img_rotate)
采用rotate()函數(shù)將圖像順時(shí)針旋轉(zhuǎn)90°。
5.2方式二
# 旋轉(zhuǎn)2
rotateM = cv.getRotationMatrix2D((80, 100), 45, 1)
img_rotate = cv.warpAffine(img, rotateM, dsize=(500, 500))
show(img_rotate)
?
采用getRotationMatrix2D()函數(shù),定義旋轉(zhuǎn)圖像所要圍繞的中心點(diǎn)(80,100),定義旋轉(zhuǎn)的角度為45°,定義縮放因子為1。進(jìn)行旋轉(zhuǎn)變換,并調(diào)整尺寸為(500,500)。
5.3設(shè)置不同縮放因子時(shí)的旋轉(zhuǎn)效果
# 旋轉(zhuǎn)scale
rotateM1 = cv.getRotationMatrix2D((80, 100), 45, 0.8)
rotateM2 = cv.getRotationMatrix2D((80, 100), 45, 1)
rotateM3 = cv.getRotationMatrix2D((80, 100), 45, 1.2)
img_rotate1 = cv.warpAffine(img, rotateM1, dsize=(700, 300))
img_rotate2 = cv.warpAffine(img, rotateM2, dsize=(700, 300))
img_rotate3 = cv.warpAffine(img, rotateM3, dsize=(700, 300))
show(np.hstack([img_rotate1, img_rotate2, img_rotate3]))
?
如圖,縮放因子越大,圖像顯示越大。?
?6.放大縮小
# 放大、縮小
img_resize = cv.resize(img, (300, 200))
show(img_resize)
?
采用 resize()函數(shù)對(duì)尺寸進(jìn)行重新定義,設(shè)置尺寸為(300,200)。
?7.透視變換
透視變換原理:選取圖像中四點(diǎn)的坐標(biāo)(一般四點(diǎn)呈現(xiàn)平行四邊形,根據(jù)圖像位置來(lái)判定選?。?,再另外選擇四點(diǎn)坐標(biāo)(一般為矩形,根據(jù)自己想要呈現(xiàn)的效果來(lái)選取),分為兩種矩陣src和dst,其中src為變換前選取的坐標(biāo)矩陣,dst為想要變換的坐標(biāo)矩陣。并采用getPerspectiveTransform()函數(shù)構(gòu)造計(jì)算后的變換矩陣。并用warpPerspective()函數(shù)進(jìn)行透視變換。如今,透視變換主要用于車道檢測(cè)和圖片矯正。
import cv2 as cv
img = cv.imread('pic/parthenon500x750.jpg')
show(img)
src = np.array([
[210, 50],
[610, 270],
[650, 480],
[150, 450]
], dtype=np.float32)
dst = np.array([
[150, 50],
[650, 50],
[650, 480],
[150, 480]
], dtype=np.float32)
M = cv.getPerspectiveTransform(src, dst)
img2 = cv.warpPerspective(img, M, dsize=(750, 500))
show(img2)
?構(gòu)造的變換矩陣M為:
array([[ 2.71437487e-01, 1.50299394e-01, 5.07376979e+01], [-6.40928318e-01, 1.08051969e+00, 1.18987142e+02], [-1.23293942e-03, 5.45617563e-04, 1.00000000e+00]])
?
?如圖,左邊為原圖,右邊為透視變換后的效果。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-502922.html
?? 創(chuàng)作不易,期待大佬們的三連支持!??文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-502922.html
到了這里,關(guān)于python圖像處理實(shí)戰(zhàn)(三)—圖像幾何變換的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!