前言
????????處理圖像時,翻轉、旋轉、平移等操作很常用。OpenCV 提供了簡單的方法實現這些變換,本文帶你快速學會用它做圖像翻轉和仿射變換。
1 圖像翻轉(圖像鏡像旋轉)
在OpenCV中,圖片的鏡像旋轉是以圖像的中心為原點進行鏡像翻轉的。
cv2.flip(img,flipcode)
參數
img: 要翻轉的圖像
flipcode: 指定翻轉類型的標志
flipcode=0: 垂直翻轉,圖片像素點沿x軸翻轉
flipcode>0: 水平翻轉,圖片像素點沿y軸翻轉
flipcode<0: 水平垂直翻轉,水平翻轉和垂直翻轉的結合
示例:
import cv2 as cv
face = cv.imread('../images/face.png')
cv.imshow('face', face)
# 翻轉 鏡像旋轉 以圖像中心為原點cv.filp(img, filpcode)
# flipcode = 0垂直翻轉 沿x軸 上下翻轉
flip_0 = cv.flip(face, 0)
cv.imshow('flip_0', flip_0)
# flipcode = 1垂直翻轉 沿y軸 左右翻轉
flip_1 = cv.flip(face, 1)
cv.imshow('flip_1', flip_1)
# flipcode = -1垂直+水平翻轉
flip = cv.flip(face, -1)
cv.imshow('flip_-1', flip)
cv.waitKey(0)
cv.destroyAllWindows()
結果如下
2 圖像仿射變換
????????仿射變換(Affine Transformation)是一種線性變換,保持了點之間的相對距離不變。
仿射變換的基本性質
保持直線
保持平行
比例不變性
不保持角度和長度
常見的仿射變換類型
旋轉:繞著某個點或軸旋轉一定角度。
平移:僅改變物體的位置,不改變其形狀和大小。
縮放:改變物體的大小。
剪切:使物體發生傾斜變形。
仿射變換的基本原理
線性變換
二維空間中,圖像點坐標為(x,y),仿射變換的目標是將這些點映射到新的位置 (x', y')。
為了實現這種映射,通常會使用一個矩陣乘法的形式:
(類似于y=kx+b)
a,b,c,d 是線性變換部分的系數,控制旋轉、縮放和剪切。
t_x,t_y 是平移部分的系數,控制圖像在平面上的移動。
輸入點的坐標被擴展為齊次坐標形式[x,y,1],以便能夠同時處理線性變換和平移
cv2.warpAffine()函數
仿射變換函數
cv2.warpAffine(img,M,dsize)
img:輸入圖像。
M:2x3的變換矩陣,類型為
np.float32
。dsize:輸出圖像的尺寸,形式為
(width,height)
。
2.1 圖像旋轉
????????旋轉圖像可以將圖像繞著某個點旋轉一定的角度。
cv2.getRotationMatrix2D()函數
獲取旋轉矩陣
cv2.getRotationMatrix2D(center,angle,scale)
center:旋轉中心點的坐標,格式為
(x,y)
。angle:旋轉角度,單位為度,正值表示逆時針旋轉負值表示順時針旋轉。
scale:縮放比例,若設為1,則不縮放。
返回值:M,2x3的旋轉矩陣。
示例:
import cv2
import cv2 as cv
# 讀圖
pig = cv.imread('../images/pig.png')
pig = cv.resize(pig, (520,520))
# 獲取旋轉矩陣 cv2.getRotationMatrix2D(center,angle,scale)
M = cv2.getRotationMatrix2D((260, 260), -45, 1)
# 仿射變換函數cv.warpAffine(img,M,(w,h)
dst = cv.warpAffine(pig, M, (pig.shape[1], pig.shape[0]))
cv.imshow('pig', pig)
cv.imshow('pig_new', dst)
cv.waitKey(0)
cv.destroyAllWindows()
2.2 圖像平移
移操作可以將圖像中的每個點沿著某個方向移動一定的距離。
假設我們有一個點 P(x,y),希望將其沿x軸方向平移t_x*個單位,沿y軸方向平移t_y個單位到新的位置P′(x′,y′),那么平移公式如下:
x′=x+tx
y′=y+ty
在矩陣形式下,該變換可以表示為:
????????這里的t_x和t_y分別代表在x軸和y軸上的平移量。
示例:
import cv2
import cv2 as cv
import numpy as np# 讀圖
pig = cv.imread('../images/pig.png')
pig = cv.resize(pig, (520,520))
# 定義偏移量
tx = 80
ty = 120
# 定義平移矩陣
M = np.float32([[1, 0, tx], [0, 1, ty]])
# 仿射變換矩陣,找不到的就用黑色填充
dst = cv.warpAffine(pig, M, (520, 520))
cv.imshow('pig', pig)
cv.imshow('pig_new', dst)
cv.waitKey(0)
cv.destroyAllWindows()
2.3 圖像縮放
縮放操作可以改變圖片的大小。
假設要把圖像的寬高分別縮放為0.5和0.8,那么對應的縮放因子sx=0.5,sy=0.8。
點P(x,y)對應到新的位置P'(x',y'),縮放公式為:
x′=sx*x
y′=sy*y
在矩陣形式下,該變換可以表示為:
相較于圖像旋轉中只能等比例的縮放,圖像縮放更加靈活,可以在指定方向上進行縮放。
sx和sy分別表示在x軸和y軸方向上的縮放因子。
示例:
import cv2 as cv
import numpy as np# 讀圖
pig = cv.imread('../images/pig.png')
pig = cv.resize(pig, (520,520))
# 定義縮放移量
sx = 0.6
sy = 0.5
# 定義縮放矩陣
M = np.float32([[sx, 0, 0], [0, sy, 0]])
# 仿射變換矩陣,找不到的就用黑色填充
dst = cv.warpAffine(pig, M, (520, 520))
cv.imshow('pig', pig)
cv.imshow('pig_new', dst)
cv.waitKey(0)
cv.destroyAllWindows()
2.4 圖像剪切(了解即可)
剪切操作可以改變圖形的形狀,以便其在某個方向上傾斜,它將對象的形狀改變為斜邊平行四邊形,而不改變其面積。
想象我們手上有一張矩形紙片,如果你固定紙片的一邊,并沿著另一邊施加一個平行于該邊的力,這張紙片就會變形為一個平行四邊形。這就是剪切變換的一個直觀解釋。
對于二維空間中的點P(x,y),對他進行剪切變換:
沿x軸剪切:x'=x+shy*y? ? ? ?y'=y
沿y軸剪切:x'=x? ? ? ?y'=shx*x+y
當需要同時沿兩個方向進行剪切時,x'=x+shy*y , y'=shx*x+y
在矩陣形式下,該變換可以表示為:
來一個圖理解一下:
?
shy和shx分別對應沿x軸和y軸方向上的剪切因子。
可以理解為,x不變,y偏移
總結:
????????本文講了 OpenCV 的兩種圖像變換。用cv.flip()
能輕松實現圖像的垂直、水平翻轉。仿射變換里,通過矩陣設置,結合cv.warpAffine()
可完成旋轉、平移、縮放和剪切。這些基礎操作是圖像處理的必備技能,多練就能熟練掌握。