日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

youcans 的 OpenCV 学习课—5.图像的几何变换

發布時間:2025/3/15 编程问答 40 豆豆
生活随笔 收集整理的這篇文章主要介紹了 youcans 的 OpenCV 学习课—5.图像的几何变换 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

youcans 的 OpenCV 學習課—5.圖像的幾何變換


本系列面向 Python 小白,從零開始實戰解說 OpenCV 項目實戰。

幾何變換是指對圖像的位置、大小、形狀、投影進行變換,是將圖像從原始平面投影到新的視平面。OpenCV 中的圖像以多維數組描述,幾何變換本質上是將一個多維數組通過映射關系求得另一個多維數組。

本節介紹圖像的幾何變換,提供完整例程和運行結果:位置變換:平移,旋轉,鏡像;形狀變換:縮放,扭變;投影變換:透視投影,平行投影;極坐標變換。


歡迎關注 『youcans 的 OpenCV 學習課』 系列,持續更新
youcans 的 OpenCV 學習課—1.安裝與環境配置
youcans 的 OpenCV 學習課—2.圖像讀取與顯示
youcans 的 OpenCV 學習課—3.圖像的創建與修改
youcans 的 OpenCV 學習課—4.圖像的疊加與混合
youcans 的 OpenCV 學習課—5.圖像的幾何變換
youcans 的 OpenCV 學習課—6.灰度變換與直方圖處理
youcans 的 OpenCV 學習課—7.空間域圖像濾波
youcans 的 OpenCV 學習課—8.頻率域圖像濾波(上)
youcans 的 OpenCV 學習課—9.頻率域圖像濾波(下)



1. 幾何變換簡介

幾何變換是指對對圖像的位置、大小、形狀、投影進行變換,是將圖像從原始平面投影到新的視平面。OpenCV 中的圖像以多維數組描述,幾何變換本質上是將一個多維數組通過映射關系求得另一個多維數組。

幾何變換可以分為等距變換、相似變換、仿射變換和投影變換。在很多書籍中把等距變換、相似變換都稱為仿射變換,常見的仿射變換包括平移、旋轉、縮放、翻轉、斜切等方法。

  • 等距變換:圖像中的長度、面積不變,典型的等距變換是 平移、旋轉
  • 相似變換:圖像中的長度比、夾角、虛圓點不變,相似變換是在等距變換的基礎上進行了縮放,典型的相似變換是 縮放
  • 仿射變換:圖像中的平行關系、面積比、共線線段或平行線段的長度比、矢量的線性組合不變,仿射變換是旋轉和非均勻縮放的復合,典型的仿射變換是 斜切
  • 投影變換:圖像中的共點、共線、相交、相切、拐點的關系不變,,投影變換是在仿射變換基礎上進行的非線性縮放,典型的投影變換是 透視

1.1 仿射變換

仿射變換(affine)的特點是原始圖像中的平行關系和線段長度比例關系保持不變。

OpenCV 中的圖像以多維數組描述,通過仿射變換變換為另一個多維數組(轉換圖像)。

仿射變換中的校正圖像在二維空間中完成,在幾何上定義為一個線性變換接一個平移變換。

仿射變換由以下公式描述:
[x~y~1]=MA[xy1],MA=[a11a12a13a21a22a23001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_A \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_A= \begin{bmatrix} a_{11} &a_{12} &a_{13}\\ a_{21} &a_{22} &a_{23}\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MA????xy1????,MA?=???a11?a21?0?a12?a22?0?a13?a23?1????

OpenCV 提供了 cv2.warpAffine 函數實現仿射變換的操作。

仿射變換矩陣 MA 中有 6 個未知參數,cv2.getAffineTransform 根據圖像中不共線的 3 個點在變換前后的對應位置坐標,構造 6元一次方程組即可求出仿射變換矩陣 MA。cv2.warpAffine 再用變換矩陣 MA 計算得到變換后的圖像。

基本例程:1.33 圖像的仿射變換

# 1.33 仿射變換: 平移、鏡像、旋轉 (cv2.warpAffine)img = cv2.imread("../images/imgB2.jpg") # 讀取彩色圖像(BGR)rows, cols, ch = img.shapepts1 = np.float32([[50, 50], [200, 50], [50, 200]]) # 初始位置pts2 = np.float32([[50, 100], [200, 50], [100, 250]]) # 終止位置MA = cv2.getAffineTransform(pts1, pts2) # 計算 2x3 變換矩陣 MAdst = cv2.warpAffine(img, MA, (cols, rows)) # 實現仿射變換plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("warpAffine")plt.show()


1.2 投影變換

投影變換(Projective mapping)也稱透視變換(Perspective transformation),其特點是:原始圖像中的平行關系、比例關系在轉換后可以改變,但直線在轉換后仍然保持直線。

投影變換將圖片投影到一個新的視平面(Viewing plane),可以對三維空間中的物體旋轉進行校正,主要用于圖像拼接和校正透視投影導致的圖像失真 。


投影變換由以下公式描述:
[x~y~z~]=M[xyz],M=[a11a12a13a21a22a23a31a32a33]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ \tilde{z} \end{bmatrix} = M \begin{bmatrix} x\\ y\\ z \end{bmatrix} ,\hspace{1em} M= \begin{bmatrix} a_{11} &a_{12} &a_{13}\\ a_{21} &a_{22} &a_{23}\\ a_{31} &a_{32} &a_{33} \end{bmatrix} ???x~y~?z~????=M???xyz????,M=???a11?a21?a31??a12?a22?a32??a13?a23?a33?????

OpenCV 提供了 cv2.warpPerspective 函數實現投影變換的操作。cv2.getPerspectiveTransform 根據圖像中不共線的 4 個點在變換前后的對應位置求得 (3x3) 變換矩陣,cv2.warpPerspective 使用該 (3x3) 變換矩陣即可求出變換后的圖像。

1.3 極坐標變換

極坐標變換可以校正圖像中的圓形物體和圓環中所包含的物體。

極坐標變換由以下公式描述:

KaTeX parse error: No such environment: align* at position 8: \begin{?a?l?i?g?n?*?}? r &= \sqrt{(x-…

OpenCV 提供了 cv2.cartToPolar 函數和 cv2.ploarToCart 函數實現笛卡爾坐標與極坐標的相互轉換。



2. 圖像的平移

平移是物體位置在水平和垂直方向的移動。

像素點 (x,y) 沿 x 軸平移 dx、沿 y 軸平移 dy,可以由以下公式描述:
[x~y~1]=MAT[xy1],MAT=[10dx01dy001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AT} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AT} = \begin{bmatrix} 1 &0 &d_x\\ 0 &1 &d_y\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MAT????xy1????,MAT?=???100?010?dx?dy?1????

由偏移量 (Tx, Ty) 按上式構造平移變換矩陣 MAT,由函數 cv2.warpAffine 可以計算變換后的平移圖像。

函數說明:

cv2.warpAffine(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

函數 cv2.warpAffine() 通過變換矩陣 M 對圖像 src 進行仿射變換。

參數說明:

  • scr:變換操作的輸入圖像
  • M:仿射變換矩陣,2行3列
  • dsize: 輸出圖像的大小,二元元組 (width, height)
  • dst:變換操作的輸出圖像,可選項
  • flags:插值方法,整型(int),可選項
    • cv2.INTER_LINEAR:線性插值,默認選項
    • cv2.INTER_NEAREST:最近鄰插值
    • cv2.INTER_AREA:區域插值
    • cv2.INTER_CUBIC:三次樣條插值
    • cv2.INTER_LANCZOS4:Lanczos 插值
  • borderMode:邊界像素方法,整型(int),可選項,默認值為 cv2.BORDER_REFLECT
  • borderValue:邊界填充值,可選項,默認值為 0(黑色填充)
  • 返回值:dst,變換操作的輸出圖像,ndarray 多維數組

注意事項:

  • 變換前后的圖像 src、dst 都是 ndarray 二維數組。
  • 變換矩陣 M 反映平移或旋轉的關系,是 np.float32 類型 ndarray 二維數組(2行*3列)。
  • 平移變換矩陣 M = [(1,0,dx), (0,1,dy)],Tx 表示向右(負值向左)移動像素點數,Ty 表示向下(負值向上)移動像素點數。
  • 輸出圖像的大小 dsize 的格式為元組 (width,height)。

  • 基本例程:1.34 圖像的平移

    # 1.34 圖像平移 (Translation transform)img = cv2.imread("../images/imgLena.tif") # 讀取彩色圖像(BGR)rows, cols, ch = img.shapedx, dy = 100, 50 # dx=100 向右偏移量, dy=50 向下偏移量MAT = np.float32([[1, 0, dx], [0, 1, dy]]) # 構造平移變換矩陣 # dst = cv2.warpAffine(img, MAT, (cols, rows)) # 默認為黑色填充dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255,255,255)) # 設置白色填充plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("Translational")plt.show()



    3. 圖像的旋轉

    • 圖像以原點 (0, 0) 為中心、順時針旋轉角度 θ 進行旋轉操作,可以由以下公式描述:

    [x~y~1]=MAR[xy1],MAR=[cosθ?sinθ0sinθcosθ0001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AR} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} , M_{AR} = \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MAR????xy1????,MAR?=???cosθsinθ0??sinθcosθ0?001????

    按上式構造旋轉變換矩陣 MAR,由函數 cv2.warpAffine 可以計算變換后的繞原點旋轉圖像。

    • 圖像以任意點 (x0, y0) 為旋轉中心、順時針旋轉角度 θ 的旋轉操作,可以先將原點平移到旋轉中心 (x0, y0) ,然后按照原點旋轉,最后再平移回坐標原點,可以由以下公式描述:

    [x~y~1]=[10x001y0001][cosθ?sinθ0sinθcosθ0001][10?x001?y0001][xy1]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix}= \begin{bmatrix} 1 &0 &x_0\\ 0 &1 &y_0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} 1 &0 &-x_0\\ 0 &1 &-y_0\\ 0 &0 &1 \end{bmatrix} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ???x~y~?1????=???100?010?x0?y0?1???????cosθsinθ0??sinθcosθ0?001???????100?010??x0??y0?1???????xy1????

    • 簡便地,OpenCV 提供了 cv2.getRotationMatrix2D 函數, 根據旋轉角度和位移計算旋轉變換矩陣 MAR。

    函數說明:

    cv2.getRotationMatrix2D(center, angle, scale) → M

    函數 getRotationMatrix2D 根據旋轉參數計算旋轉變換矩陣 MAR。

    參數說明:

    • center:旋轉中心坐標,二元元組 (x0, y0)
    • angle:旋轉角度,單位為角度,逆時針為正數,順時針為負數
    • scale: 縮放因子
    • 返回值:M, 旋轉變換矩陣,2行3列

    注意事項:

  • 求出旋轉變換矩陣 MAR,由函數 cv2.warpAffine 可以實現任意角度和任意中心的旋轉效果。
  • 以圖像中心作為旋轉中心時,可以用 img.shape 獲得圖像的寬度和高度值,除以 2 就是圖像中心點坐標。
  • 旋轉角度為 90,180,270 度時,可以用 cv2.rotate(src, rotateCode) 函數實現,該方法實際上是通過矩陣轉置實現的,因此速度很快。

  • 基本例程:1.35 圖像的旋轉(以原點為中心旋轉)

    # 1.35 圖像旋轉 (以原點 (0,0) 為中心旋轉)img = cv2.imread("../images/imgLena.tif") # 讀取彩色圖像(BGR)rows, cols, ch = img.shapetheta = np.pi / 8.0 # 順時針旋轉角度cosTheta = np.cos(theta)sinTheta = np.sin(theta)MAT = np.float32([[cosTheta, -sinTheta, 0], [sinTheta, cosTheta, 0]]) # 構造旋轉變換矩陣# dst = cv2.warpAffine(img, MAT, (cols, rows)) # 默認為黑色填充dst = cv2.warpAffine(img, MAT, (cols, rows), borderValue=(255,255,255)) # 設置白色填充plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Origin")plt.subplot(122), plt.imshow(cv2.cvtColor(dst, cv2.COLOR_BGR2RGB)), plt.title("Rotation")plt.show()



    基本例程:1.36 圖像的旋轉(任意旋轉中心)

    # 1.36 圖像旋轉 (以任意點 (x0,y0) 為中心旋轉)img = cv2.imread("../images/imgGaia.tif") # 讀取彩色圖像(BGR)height, width = img.shape[:2] # 圖片的高度和寬度theta1, theta2 = 30, 45 # 順時針旋轉角度,單位為角度x0, y0 = width//2, height//2 # 以圖像中心作為旋轉中心MAR1 = cv2.getRotationMatrix2D((x0,y0), theta1, 1.0)MAR2 = cv2.getRotationMatrix2D((x0,y0), theta2, 1.0)imgR1 = cv2.warpAffine(img, MAR1, (width, height)) # 旋轉變換,默認為黑色填充imgR2 = cv2.warpAffine(img, MAR2, (width, height), borderValue=(255,255,255)) # 設置白色填充plt.figure(figsize=(10,6))plt.subplot(131), plt.axis('off'), plt.title(r"$Origin$")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB))plt.subplot(132), plt.axis('off'), plt.title(r"$Rotation {}^o$".format(theta1))plt.imshow(cv2.cvtColor(imgR1, cv2.COLOR_BGR2RGB))plt.subplot(133), plt.axis('off'), plt.title(r"$Rotation {}^o$".format(theta2))plt.imshow(cv2.cvtColor(imgR2, cv2.COLOR_BGR2RGB))plt.show()



    擴展例程:1.37 圖像的直角旋轉

    當旋轉角度為 90,180,270 度時,可以用圖像旋轉函數 cv2.rotate(src, rotateCode) 實現,該方法通過矩陣轉置實現,速度很快。此外,numpy 中也提供了旋轉矩陣的方法 np.rot90 可以按 90 度的整數倍進行旋轉。

    # 1.37 圖像的直角旋轉 (90, 180, 270)# cv2.rotate(src, rotateCode)# rotateCode: cv2.ROTATE_90_CLOCKWISE, 順時針旋轉90度# cv2.ROTATE_180, 順時針旋轉180度# cv2.ROTATE_90_COUNTERCLOCKWISE, 順時針旋轉270度img = cv2.imread("../images/imgLena.tif") # 讀取彩色圖像(BGR)imgR90 = cv2.rotate(img, cv2.ROTATE_90_CLOCKWISE)imgR180 = cv2.rotate(img, cv2.ROTATE_180)imgR270 = cv2.rotate(img, cv2.ROTATE_90_COUNTERCLOCKWISE)# imgR90 = np.rot90(img, 1) # numpy 矩陣旋轉 90*1=90 度# imgR180 = np.rot90(img, 2) # numpy 矩陣旋轉 90*2=180 度# imgR270 = np.rot90(img, 3) # numpy 矩陣旋轉 90*3=270 度plt.figure(figsize=(9,7))plt.subplot(221), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title(r"$Origin$")plt.subplot(222), plt.imshow(cv2.cvtColor(imgR90, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 90^{o}$")plt.subplot(223), plt.imshow(cv2.cvtColor(imgR180, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 180^{o}$")plt.subplot(224), plt.imshow(cv2.cvtColor(imgR270, cv2.COLOR_BGR2RGB)), plt.title(r"$Rotation 270^{o}$")plt.show()



    4. 圖像的翻轉(鏡像)

    翻轉也稱鏡像,是指將圖像沿軸線進行軸對稱變換。水平鏡像是將圖像沿垂直中軸線進行左右翻轉,垂直鏡像是將圖像沿水平中軸線進行上下翻轉,水平垂直鏡像是水平鏡像和垂直鏡像的疊加。

    以水平鏡像為例,圖像寬度為 fw,像素點 (x,y) 以垂直中軸線為中心進行左右對換,可以由以下公式描述:
    [x~y~1]=MAF[xy1],MAF=[?10fw010001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AF} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AF} = \begin{bmatrix} -1 &0 &f_w\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MAF????xy1????,MAF?=????100?010?fw?01????

    由上式構造鏡像變換矩陣 MAF,由函數 cv2.warpAffine 可以計算變換后的鏡像圖像。

    簡便地,OpenCV 提供了 cv2.flip 函數,可以將圖像沿水平方向、垂直方向、或水平/垂直方向同時進行翻轉。

    函數說明:

    cv2.flip(src, flipCode[, dst]) -> dst

    參數說明:

    • scr:變換操作的輸入圖像
    • flipCode:控制參數,整型(int),flipCode>0 水平翻轉,flipCode=0 垂直翻轉,flipCode<0 水平和垂直翻轉
    • dst:變換操作的輸出圖像,可選項

    基本例程:1.38 圖像的翻轉(鏡像)

    # 1.38 圖像的翻轉 (鏡像)img = cv2.imread("../images/Fractal03.png") # 讀取彩色圖像(BGR)imgFlip1 = cv2.flip(img, 0) # 垂直翻轉imgFlip2 = cv2.flip(img, 1) # 水平翻轉imgFlip3 = cv2.flip(img, -1) # 水平和垂直翻轉plt.figure(figsize=(9, 6))plt.subplot(221), plt.axis('off'), plt.title("Original")plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)) # 原始圖像plt.subplot(222), plt.axis('off'), plt.title("Flipped Horizontally")plt.imshow(cv2.cvtColor(imgFlip2, cv2.COLOR_BGR2RGB)) # 水平翻轉plt.subplot(223), plt.axis('off'), plt.title("Flipped Vertically")plt.imshow(cv2.cvtColor(imgFlip1, cv2.COLOR_BGR2RGB)) # 垂直翻轉plt.subplot(224), plt.axis('off'), plt.title("Flipped Horizontally & Vertically")plt.imshow(cv2.cvtColor(imgFlip3, cv2.COLOR_BGR2RGB)) # 水平垂直翻轉plt.show()



    5. 圖像的縮放

    縮放只是調整圖像的大小。

    OpenCV 提供了 cv2.resize 函數,實現圖像的縮放和大小變換 。

    函數說明:

    cv2.resize(src, dsize[, dst[, fx[, fy[, interpolation]]]]) → dst

    參數說明:

    • scr:變換操作的輸入圖像
    • dsize: 輸出圖像的大小,二元元組 (width, height)
    • dst:變換操作的輸出圖像,可選項
    • fx, fy:x 軸、y 軸上的縮放比例,實型,可選項
    • interpolation:插值方法,整型,可選項
      • cv2.INTER_LINEAR:雙線性插值(默認方法)
      • cv2.INTER_AREA:使用像素區域關系重采樣,縮小圖像時可以避免波紋出現
      • cv2.INTER_NEAREST:最近鄰插值
      • cv2.INTER_CUBIC:4x4 像素鄰域的雙三次插值
      • cv2.INTER_LANCZOS4:8x8 像素鄰域的Lanczos插值
    • 返回值:dst,變換操作的輸出圖像,ndarray 多維數組

    注意事項:

  • 圖像縮放可以通過 dsize 直接設定輸出圖像的大小,也可以通過 dx, dy 設置圖像縮放的比例(dsize 設為 None)。

  • 也可以通過構造縮放變換矩陣 MAZ,由函數 cv2.warpAffine 計算變換后的縮放平移圖像。縮放變換矩陣 MAZ 由以下公式描述:

  • [x~y~1]=MAZ[xy1],MAZ=[fx000fy0001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AZ} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AZ} = \begin{bmatrix} f_x &0 &0\\ 0 &f_y &0\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MAZ????xy1????,MAZ?=???fx?00?0fy?0?001????

    由偏移量 (Tx, Ty) 按上式構造平移變換矩陣 MAT,由函數 cv2.warpAffine 可以計算變換后的平移圖像。


    基本例程:1.39 圖像的縮放變換

    # 1.39 圖像的縮放img = cv2.imread("../images/Fractal08.png") # 讀取彩色圖像(BGR)height, width = img.shape[:2] # 圖片的高度和寬度imgZoom1 = cv2.resize(img, (int(0.75*width), int(height)))imgZoom2 = cv2.resize(img, None, fx=0.75, fy=1.0, interpolation=cv2.INTER_AREA)plt.figure(figsize=(8,6))plt.subplot(121), plt.axis('off'), plt.title("Zoom: 0.75*W,1.0*H")plt.imshow(cv2.cvtColor(imgZoom1, cv2.COLOR_BGR2RGB))plt.subplot(122), plt.axis('off'), plt.title("Zoom: fx=0.75,fy=1.0")plt.imshow(cv2.cvtColor(imgZoom2, cv2.COLOR_BGR2RGB))plt.show()


    擴展例程:1.40 圖像金字塔

    圖像金字塔是一種以多分辨率來解釋圖像的結構,常用于圖像分割、圖像壓縮和機器視覺。

    在需要處理同一圖像的不同分辨率的子圖時,需要創建一組具有不同分辨率的原始圖像。把最大的圖像放在底部,最小的放在頂部,看起來就像一座金字塔,稱為圖像金字塔。

    圖像金字塔是一系列來源于同一張原始圖像、以金字塔形狀排列的分辨率逐步降低的圖像集合。
    金字塔的底部是原始圖像的高分辨率的表示,頂部是低分辨率的近似。

    OpenCV 為向下采樣和向上采樣提供了兩個函數:cv2.pyrDowncv2.pyrUp

    函數說明:

    cv2.pyrDown(src, dst=None, dstsize=None, borderType=None) → dst # 向下采樣 cv2.pyrUp(src, dst=None, dstsize=None, borderType=None) → dst # 向上采樣

    函數 cv2.pyrDown 是從高分辨率的大尺寸圖像逐次向下采樣得到一系列圖像,構建一個金字塔,稱為高斯金字塔(Gaussian pyramid),實際上是一個重復高斯平滑并重新對圖像采樣的過程。拉普拉斯金字塔每次向下采樣后將再次向上采樣,并記錄殘差信息,可以對圖像進行最大程度的還原。

    # 1.40 圖像金字塔def GussianPyramid(image): # 高斯金字塔level = 2 # 金字塔的層數imgCopy = image.copy()pyramidImages = [] # 創建圖像 Listfor i in range(level):dst = cv2.pyrDown(imgCopy) # 下采樣pyramidImages.append(dst) # 添加到圖像 Listcv2.imshow("pyramid down "+str(i), dst)imgCopy = dst.copy()return pyramidImagesimg = cv2.imread("../images/imgLena.tif") # 讀取彩色圖像(BGR) cv2.namedWindow("input image", cv2.WINDOW_AUTOSIZE) cv2.imshow("input image", img) GussianPyramid(img) # 高斯圖像金字塔 # LapalianPyramid(img) # 拉普拉斯圖像金字塔 cv2.waitKey(0)



    6. 圖像的扭變(錯切)

    圖像的錯切變換也稱斜切,是指平面景物在投影平面上的非垂直投影,使圖像中的圖形在水平方向或垂直方向產生扭變。

    以水平扭變為例,像素點 (x,y) 在水平方向發生扭變變成斜邊,而在垂直方向的邊不變,可以由以下公式描述:
    [x~y~1]=MAS[xy1],MAS=[1tanθ0010001]\begin{bmatrix} \tilde{x}\\ \tilde{y}\\ 1 \end{bmatrix} = M_{AS} \begin{bmatrix} x\\ y\\ 1 \end{bmatrix} ,\hspace{1em} M_{AS} = \begin{bmatrix} 1 &tan \theta &0\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} ???x~y~?1????=MAS????xy1????,MAS?=???100?tanθ10?001????

    由扭變角度 θ上式構造錯切變換矩陣 MAS,由函數 cv2.warpAffine 可以計算變換后的扭變圖像。


    基本例程:1.41 圖像的錯切

    # 1.41 圖像的錯切img = cv2.imread("../images/imgB2.jpg") # 讀取彩色圖像(BGR)height, width = img.shape[:2] # 圖片的高度和寬度MAS = np.float32([[1, 0.2, 0], [0, 1, 0]]) # 構造錯切變換矩陣imgShear = cv2.warpAffine(img, MAS, (width, height))plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("imgOrigin")plt.subplot(122), plt.imshow(cv2.cvtColor(imgShear, cv2.COLOR_BGR2RGB)), plt.title("imgShear")plt.show()



    7. 圖像的復合變換

    圖像的復合變換是指對給定的圖像連續進行多次上述的平移、旋轉、翻轉、縮放、錯切等基本變換,也稱為級聯變換。

    對給定圖像按一定順序執行若干次基本變換,其變換矩陣仍然可以用 3x3 階變換矩陣表示。進一步地,對圖像依次執行基本變換 F1、F2、…Fn 的變換矩陣分別為 M1、M2、…Mn,可以證明,以圖像中心點為中心進行比例、旋轉進行變換,則復合變換的變換矩陣 M 等于各基本變換矩陣依次相乘所得到的組合矩陣:
    M=M1×M2×?×MnM = M_1 \times M_2 \times \dots \times M_n M=M1?×M2?×?×Mn?

    縮放:
    MAZ=[fx000fy0001]M_{AZ} = \begin{bmatrix} fx &0 &0\\ 0 &f_y &0\\ 0 &0 &1 \end{bmatrix} MAZ?=???fx00?0fy?0?001????

    旋轉:
    MAR=[cosθ?sinθ0sinθcosθ0001]M_{AR} = \begin{bmatrix} cos \theta &-sin \theta &0\\ sin \theta &cos \theta &0\\ 0 &0 &1 \end{bmatrix} MAR?=???cosθsinθ0??sinθcosθ0?001????

    平移:
    MAT=[10dx01dy001]M_{AT} = \begin{bmatrix} 1 &0 &d_x\\ 0 &1 &d_y\\ 0 &0 &1 \end{bmatrix} MAT?=???100?010?dx?dy?1????

    扭變:
    MAS=[1tanθ0010001]M_{AS} = \begin{bmatrix} 1 &tan \theta &0\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} MAS?=???100?tanθ10?001????

    鏡像:
    MAF=[?10fw010001]M_{AF} = \begin{bmatrix} -1 &0 &f_w\\ 0 &1 &0\\ 0 &0 &1 \end{bmatrix} MAF?=????100?010?fw?01????


    基本例程:1.42 圖像的復合變換

    # 1.42 圖像的復合變換img = cv2.imread("../images/imgLena.tif") # 讀取彩色圖像(BGR)height, width = img.shape[:2] # 圖片的高度和寬度# (1) 縮放fx, fy = 0.6, 0.6MAZ = np.float32([[fx, 0, 0], [0, fy, 0]]) # 構造縮放變換矩陣imgT1 = cv2.warpAffine(img, MAZ, (width, height)) # 仿射變換, 黑色填充# (2) 平移dx, dy = 50, 200 # dx=100 向右偏移量, dy=50 向下偏移量MAT = np.float32([[1, 0, dx], [0, 1, dy]]) # 構造平移變換矩陣imgT2 = cv2.warpAffine(imgT1, MAT, (width, height), borderValue=(0,255,255)) # 實現仿射變換# (3) 旋轉theta = -30 * np.pi / 180 # 逆時針旋轉 30°cosTheta = np.cos(theta)sinTheta = np.sin(theta)MAR = np.float32([[cosTheta, -sinTheta, 0], [sinTheta, cosTheta, 0]]) # 構造旋轉變換矩陣imgT3 = cv2.warpAffine(imgT2, MAR, (width, height), borderValue=(255,255,0)) # 實現仿射變換# (4) 扭曲theta = -30 * np.pi / 180 # 逆時針扭變 30°MAS = np.float32([[1, np.tan(theta), 0], [0, 1, 0]]) # 構造扭變變換矩陣imgT4 = cv2.warpAffine(imgT3, MAS, (width, height), borderValue=(255,0,255)) # 實現仿射變換plt.figure(figsize=(9,6))plt.subplot(221), plt.axis('off'), plt.title("T1:Zoom")plt.imshow(cv2.cvtColor(imgT1, cv2.COLOR_BGR2RGB)),plt.subplot(222), plt.axis('off'), plt.title("T2:Translation")plt.imshow(cv2.cvtColor(imgT2, cv2.COLOR_BGR2RGB))plt.subplot(223), plt.axis('off'), plt.title("T3:Rotation")plt.imshow(cv2.cvtColor(imgT3, cv2.COLOR_BGR2RGB))plt.subplot(224), plt.axis('off'), plt.title("T4:Shear")plt.imshow(cv2.cvtColor(imgT4, cv2.COLOR_BGR2RGB))plt.show()



    8. 投影變換

    投影變換(Projective mapping)也稱透視變換(Perspective transformation)是建立兩平面場之間的對應關系, 將圖片投影到一個新的視平面(Viewing plane)。

    OpenCV 提供了 cv2.warpPerspective 函數實現投影變換的操作。

    函數說明:

    cv2.getPerspectiveTransform(src, dst[,solveMethod]) → MP cv2.warpPerspective(src, M, dsize[, dst[, flags[, borderMode[, borderValue]]]]) → dst

    函數cv2.getPerspectiveTransform 根據圖像中不共線的 4 個點在變換前后的對應位置求得 (3x3) 變換矩陣,cv2.warpPerspective 使用該 (3x3) 變換矩陣即可求出變換后的圖像。標量進行加法運算。

    參數說明:

    • src:變換前圖像四邊形頂點坐標
    • dst:變換后圖像四邊形頂點坐標
    • solveMethod:矩陣分解方法,傳遞給 cv2.solve 求解變換矩陣 MP
      • cv2.DECOMP_LU:選擇最優軸的高斯消去法,默認方法
      • cv2.DECOMP_SVD:奇異值分解(SVD)方法
      • cv2.DECOMP_EIG:特征值分解方法,src 必須對稱
      • cv2.DECOMP_QR:QR(正交三角)分解
      • cv2.DECOMP_CHOLESKY:Cholesky LLT 分解
    • MP:透視變換矩陣,3行3列
    • dsize: 輸出圖像的大小,二元元組 (width, height)
    • dst:變換操作的輸出圖像,可選項
    • flags:插值方法,整型(int),可選項
      • cv2.INTER_LINEAR:線性插值,默認選項
      • cv2.INTER_NEAREST:最近鄰插值
      • cv2.INTER_AREA:區域插值
      • cv2.INTER_CUBIC:三次樣條插值
      • cv2.INTER_LANCZOS4:Lanczos 插值
    • borderMode:邊界像素方法,整型(int),可選項,默認值為 cv2.BORDER_REFLECT
    • borderValue:邊界填充模式,可選項,默認值為 0(黑色填充)
    • 返回值:dst,透視變換操作的輸出圖像,ndarray 多維數組

    基本例程:1.43 圖像的投影變換

    # 1.43 投影變換 (Projective mapping)img = cv2.imread("../images/imgB2.jpg") # 讀取彩色圖像(BGR)h, w = img.shape[:2] # 圖片的高度和寬度pointSrc = np.float32([[0,0], [w-1,0], [0,h-100], [w-1, h-100]]) # 原始圖像中 4點坐標pointDst = np.float32([[180,50], [w-180,50], [0,h-100], [w-1, h-100]]) # 變換圖像中 4點坐標MP = cv2.getPerspectiveTransform(pointSrc, pointDst) # 計算投影變換矩陣 MimgP = cv2.warpPerspective(img, MP, (512, 512)) # 用變換矩陣 M 進行投影變換plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original")plt.subplot(122), plt.imshow(cv2.cvtColor(imgP, cv2.COLOR_BGR2RGB)), plt.title("Projective")plt.show()


    基本例程:1.44 圖像的投影變換

    # 1.44 圖像的投影變換img = cv2.imread("../images/imgC2.jpg") # 讀取彩色圖像(BGR)h, w = img.shape[:2] # 圖片的高度和寬度pointSrc = np.float32([[0,0], [w,0], [0,h], [w,h]]) # 原始圖像中 4點坐標pointDst = np.float32([[int(w/3), int(h/3)], [int(w*2/3), int(h/3)], [0,h], [w,h]]) # 變換圖像中 4點坐標MP = cv2.getPerspectiveTransform(pointSrc, pointDst) # 計算投影變換矩陣 MimgP = cv2.warpPerspective(img, MP, (w,h), flags=cv2.INTER_AREA, borderMode=cv2.BORDER_WRAP)plt.figure(figsize=(9,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original"), plt.axis('off')plt.subplot(122), plt.imshow(cv2.cvtColor(imgP, cv2.COLOR_BGR2RGB)), plt.title("Projective"), plt.axis('off')plt.show()



    9. 直角坐標與極坐標的轉換

    函數 cv2.cartToPolar 用于將直角坐標(笛卡爾坐標)轉換為極坐標,函數 cv2.polarToCart 用于將極坐標轉換為直角坐標(笛卡爾坐標)。

    圓形圖案邊緣上的文字經過及坐標變換后可以垂直的排列在新圖像的邊緣,便于對文字的識別和檢測。

    函數說明:

    cv2.cartToPolar(x, y[, magnitude[, angle[, angleInDegrees]]]) → magnitude, angle cv2.polarToCart(magnitude, angle[, x[, y[, angleInDegrees]]]) → x, y

    函數 cv2.cartToPolar 實現將原點移動到變換中心后的直角坐標向極坐標的轉換,輸入參數為直角坐標系的橫坐標、縱坐標,輸出為極坐標系的向量值、角度值。

    函數 cv2.polarToCart 實現將原點移動到變換中心后的極坐標向直角坐標的轉換,輸入參數為極坐標系的向量值、角度值,輸出為直角坐標系的橫坐標、縱坐標。

    參數說明:

    • x, y:直角坐標系的橫坐標、縱坐標,ndarray 多維數組,浮點型
    • magnitude, angle:極坐標系的向量值、角度值,ndarray 多維數組
    • angleInDegrees:弧度制/角度值選項,默認值 0 選擇弧度制,1 選擇角度制([0,360] )
    • 返回值 magnitude, angle:極坐標系的向量值、角度值,ndarray 多維數組,與輸入的 x, y 具有相同的尺寸和數據類型
    • 返回值 x, y:直角坐標系的橫坐標、縱坐標,ndarray 多維數組,與輸入的 magnitude, angle 具有相同的尺寸和數據類型

    注意事項:

  • 極坐標與直角坐標的變換在數學上是可逆的,但實際變換時存在誤差,角度計算精度約為 0.3度,坐標計算精度約為 1e-6。
  • 直角坐標系以變換中心為圓心的同一個圓上的點,在極坐標系中顯示為一條直線。因此,用極坐標變換可以實現圓形物體的圖像修正。
  • cv2.cartToPolar 中的可選項 magnitude, angle 可以用于指定變換中心的坐標,cv2.polarToCart 中的可選項 x, y 可以用于指定變換中心的坐標。

  • 基本例程:1.45 直角坐標轉換為極坐標

    # 1.45 直角坐標轉換為極坐標x = np.float32([0,1,2, 0,1,2, 0,1,2]) -1y = np.float32([0,0,0, 1,1,1, 2,2,2]) -1n = np.arange(9)r, theta = cv2.cartToPolar(x, y, angleInDegrees=True)xr,yr = cv2.polarToCart(r, theta, angleInDegrees=1)print(xr,yr)plt.figure(figsize=(9,5))plt.subplot(121), plt.title("Cartesian coordinate"), plt.plot(x, y, 'o')for i, txt in enumerate(n):plt.annotate(txt, (x[i], y[i]))plt.subplot(122), plt.title("Polar coordinate"), plt.plot(r, theta, 'o')for i, txt in enumerate(n):plt.annotate(txt, (r[i], theta[i]))plt.show()

    擴展例程:1.46 極坐標系中的圓形圖像修正

    # 1.46 極坐標系中的圓形圖像修正img = cv2.imread("../images/imgC3.jpg") # 讀取彩色圖像(BGR)h, w = img.shape[:2] # 圖片的高度和寬度cx, cy = int(w/2), int(h/2) # 以圖像中心點作為變換中心maxR = max(cx, cy) # 最大變換半徑imgPolar = cv2.linearPolar(img, (cx,cy), maxR, cv2.INTER_LINEAR)imgPR = cv2.rotate(imgPolar, cv2.ROTATE_90_COUNTERCLOCKWISE)plt.figure(figsize=(10,6))plt.subplot(121), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title("Original"), plt.axis('off')plt.subplot(122), plt.imshow(cv2.cvtColor(imgPR, cv2.COLOR_BGR2RGB)), plt.title("PolarTrans"), plt.axis('off')plt.show()

    通過極坐標和直角坐標的對應關系,將圓環圖像轉換為矩形圖像,可以對圓形圖像進行修正。


    【本節完】



    版權聲明:

    youcans 的 OpenCV 學習課 @ youcans 原創作品
    轉載必須標注原文鏈接:https://blog.csdn.net/youcans/article/details/121288020
    Copyright 2021 youcans, XUPT
    Crated:2021-11-15

    歡迎關注 『youcans 的 OpenCV 學習課』 系列,持續更新
    youcans 的 OpenCV 學習課—1.安裝與環境配置
    youcans 的 OpenCV 學習課—2.圖像讀取與顯示
    youcans 的 OpenCV 學習課—3.圖像的創建與修改
    youcans 的 OpenCV 學習課—4.圖像的疊加與混合
    youcans 的 OpenCV 學習課—5.圖像的幾何變換
    youcans 的 OpenCV 學習課—6.灰度變換與直方圖處理
    youcans 的 OpenCV 學習課—7.空間域圖像濾波
    youcans 的 OpenCV 學習課—8.頻率域圖像濾波(上)
    youcans 的 OpenCV 學習課—9.頻率域圖像濾波(下)

    總結

    以上是生活随笔為你收集整理的youcans 的 OpenCV 学习课—5.图像的几何变换的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。