目錄
一、介紹
二、仿射變換矩陣 (M)
1.M中六個(gè)元素的說(shuō)明
2.計(jì)算旋轉(zhuǎn)角度
3.M的計(jì)算過(guò)程
三、輸出狀態(tài) (inliers)
四、錯(cuò)切參數(shù)
1.錯(cuò)切參數(shù)的定義
2.錯(cuò)切參數(shù)例子
(1)水平錯(cuò)切
(2)垂直錯(cuò)切
一、介紹
????????cv2.estimateAffine2D?是 OpenCV 庫(kù)中的一個(gè)函數(shù),用于估計(jì)兩個(gè)二維點(diǎn)集之間的仿射變換矩陣。即第一個(gè)點(diǎn)集經(jīng)仿射變換轉(zhuǎn)換到第二個(gè)點(diǎn)集需要的操作,包括縮放、旋轉(zhuǎn)和平移。
? ? ? ? 先來(lái)看代碼:
import cv2
import numpy as np
# 原始點(diǎn)集
srcPoints = np.array([[50, 50], [200, 50], [50, 200]], dtype=np.float32)
# 目標(biāo)點(diǎn)集
dstPoints = np.array([[70, 100], [220, 70], [150, 250]], dtype=np.float32)
# 估計(jì)仿射變換矩陣
M, inliers = cv2.estimateAffine2D(srcPoints, dstPoints)
# 打印估計(jì)得到的仿射變換矩陣
print('M:\n', M)
'''
M:
[[ 1. 0.53333333 -6.66666667]
[-0.2 1. 60. ]]
'''
print('inliers:\n', inliers)
'''
inliers:
[[1]
[1]
[1]]
'''
? ? ? ? 從上面的代碼中可以看到,函數(shù)的輸入是兩個(gè)參數(shù),分別表示原始點(diǎn)集和目標(biāo)點(diǎn)集。函數(shù)的輸出參數(shù)包括兩個(gè)部分:仿射變換矩陣和輸出狀態(tài)。
二、仿射變換矩陣 (M)
? ? ? ? 第一個(gè)返回值是一個(gè) 2x3 的浮點(diǎn)型矩陣,表示從原始點(diǎn)集到目標(biāo)點(diǎn)集的仿射變換。矩陣的前兩列是旋轉(zhuǎn)和縮放的部分,最后一列是平移的部分??梢允褂眠@個(gè)矩陣來(lái)將原始圖像或點(diǎn)集進(jìn)行仿射變換,使其與目標(biāo)圖像或點(diǎn)集對(duì)齊。
1.M中六個(gè)元素的說(shuō)明
? ? ? ? M[0,0]:表示x方向上的縮放。大于?1,則表示進(jìn)行了放大操作;小于?1,則表示進(jìn)行了縮小操作;等于?1,則表示沒(méi)有進(jìn)行縮放操作。
????????M[0,1]:表示垂直錯(cuò)切參數(shù),與M[1,0]一起用于計(jì)算旋轉(zhuǎn)角度。
????????M[0,2]:表示x方向上的平移。
????????M[1,0]:表示水平錯(cuò)切參數(shù),與M[1,1]一起用于計(jì)算旋轉(zhuǎn)角度。
????????M[1,1]:表示y方向上的縮放。大于?1,則表示進(jìn)行了放大操作;小于?1,則表示進(jìn)行了縮小操作;等于?1,則表示沒(méi)有進(jìn)行縮放操作。
????????M[1,2]:表示y方向上的平移。
2.計(jì)算旋轉(zhuǎn)角度
? ? ? ? 旋轉(zhuǎn)角度的計(jì)算公式:
????????其中,atan2?是一個(gè)反三角函數(shù),用于計(jì)算給定的?y?值和?x?值的反正切值。這個(gè)角度表示原始點(diǎn)集經(jīng)過(guò)變換后的旋轉(zhuǎn)角度。
代碼如下,np.arctan2返回的是弧度值,如果需要角度值還需要再轉(zhuǎn)換一下:
# 得到弧度值
da = np.arctan2(m[1, 0], m[0, 0])
# 得到角度值
theta_deg = np.degrees(da)
3.M的計(jì)算過(guò)程
????????1. 首先,根據(jù)輸入的原始點(diǎn)集 srcPoints 和目標(biāo)點(diǎn)集 dstPoints,構(gòu)建一個(gè)線性方程系統(tǒng)。對(duì)于每個(gè)點(diǎn)對(duì) (srcPoint, dstPoint),構(gòu)建以下兩個(gè)方程:
????????2. 將線性方程系統(tǒng)轉(zhuǎn)化為矩陣形式 A * X = B,其中:
????????A 是一個(gè) 2N x 6 的矩陣,其中 N 是點(diǎn)對(duì)的數(shù)量。A 的每一行對(duì)應(yīng)一個(gè)點(diǎn)對(duì),包含原始點(diǎn)的坐標(biāo)和一個(gè)常數(shù)項(xiàng)。
????????X 是一個(gè) 6 x 1 的矩陣,表示待求解的仿射變換矩陣的參數(shù)。
????????B 是一個(gè) 2N x 1 的矩陣,包含目標(biāo)點(diǎn)的坐標(biāo)。
????????3. 使用最小二乘法來(lái)求解矩陣 X,使得 A * X 盡可能接近 B。最小二乘法的目標(biāo)是最小化殘差的平方和。
????????4. 根據(jù)求解得到的矩陣 X,構(gòu)建估計(jì)的仿射變換矩陣 M:
????????最小二乘法的目標(biāo)是找到一個(gè)最優(yōu)的仿射變換矩陣,使得原始點(diǎn)集經(jīng)過(guò)變換后與目標(biāo)點(diǎn)集盡可能接近。通過(guò)最小化殘差的平方和,可以得到一個(gè)最優(yōu)的估計(jì)結(jié)果。
????????需要注意的是,由于存在噪聲和異常值的影響,估計(jì)的仿射變換矩陣可能不是完全準(zhǔn)確的。因此,輸出的仿射變換矩陣 M 可能只是一個(gè)近似的估計(jì)結(jié)果,需要根據(jù)實(shí)際情況進(jìn)行評(píng)估和調(diào)整。
三、輸出狀態(tài) (inliers)
????????inliers是一個(gè)整數(shù)或浮點(diǎn)數(shù)的向量,表示每個(gè)輸入點(diǎn)對(duì)應(yīng)的輸出點(diǎn)是否被認(rèn)為是內(nèi)點(diǎn)(inlier)。內(nèi)點(diǎn)是指在估計(jì)仿射變換時(shí)被認(rèn)為是一致的點(diǎn)。輸出狀態(tài)的長(zhǎng)度與輸入點(diǎn)集的數(shù)量相同,每個(gè)元素的值為 0 或 1,其中 1 表示對(duì)應(yīng)的點(diǎn)是內(nèi)點(diǎn),0 表示對(duì)應(yīng)的點(diǎn)是外點(diǎn)(outlier)。
? ? ? ? cv2.estimateAffine2D確定內(nèi)點(diǎn)(inliers)的算法有三個(gè)可選:
? ? ? ? cv2.RANSAC: 使用?RANSAC?算法進(jìn)行估計(jì)。該選項(xiàng)適用于存在較多離群點(diǎn)的情況,可以提高估計(jì)的魯棒性,這也是默認(rèn)參數(shù)。
????????cv2.LMEDS: 使用最小中值估計(jì)(Least-Median?Estimation,LMedS)算法進(jìn)行估計(jì)。該選項(xiàng)適用于存在少量離群點(diǎn)的情況,可以提高估計(jì)的準(zhǔn)確性。
????????cv2.RHO: 使用?RHO?算法進(jìn)行估計(jì)。該選項(xiàng)適用于存在較多離群點(diǎn)的情況,可以提高估計(jì)的魯棒性。
? ? ? ? 可以通過(guò)下面的方式修改內(nèi)點(diǎn)檢測(cè)方式:
M, inliers = cv2.estimateAffine2D(srcPoints, dstPoints, cv2.RHO)
四、錯(cuò)切參數(shù)
1.錯(cuò)切參數(shù)的定義
? ? ? ? 上面提到了一個(gè)名詞叫錯(cuò)切參數(shù),這里解釋一下。錯(cuò)切參數(shù)(Shear?parameters)是一種用于描述錯(cuò)切變換的數(shù)值參數(shù)。在二維圖形變換中,錯(cuò)切變換是一種線性變換,它通過(guò)改變圖形的形狀來(lái)實(shí)現(xiàn)。
????????在二維平面上,錯(cuò)切變換是一種將對(duì)象沿著水平或垂直方向進(jìn)行平移和拉伸的變換。它會(huì)改變對(duì)象的形狀,使其在一個(gè)方向上相對(duì)于另一個(gè)方向發(fā)生傾斜。
????????在錯(cuò)切變換中,有兩個(gè)主要的錯(cuò)切參數(shù):水平錯(cuò)切參數(shù)(shear parameter)和垂直錯(cuò)切參數(shù)(shear parameter)。這些參數(shù)決定了在水平和垂直方向上的錯(cuò)切程度。
????????水平錯(cuò)切參數(shù)(shx):它表示在水平方向上的錯(cuò)切程度。當(dāng) shx 的值為正時(shí),圖形在水平方向上向右上方傾斜;當(dāng) shx 的值為負(fù)時(shí),圖形在水平方向上向左上方傾斜;當(dāng) shx 的值為零時(shí),表示沒(méi)有水平方向上的錯(cuò)切變換。
????????垂直錯(cuò)切參數(shù)(shy):它表示在垂直方向上的錯(cuò)切程度。當(dāng) shy 的值為正時(shí),圖形在垂直方向上向右下方傾斜;當(dāng) shy 的值為負(fù)時(shí),圖形在垂直方向上向左下方傾斜;當(dāng) shy 的值為零時(shí),表示沒(méi)有垂直方向上的錯(cuò)切變換。
????????這些錯(cuò)切參數(shù)可以通過(guò)仿射變換矩陣中的相應(yīng)元素來(lái)表示。在二維仿射變換矩陣中,水平錯(cuò)切參數(shù)通常對(duì)應(yīng)于矩陣的第一行第二列元素(M[0, 1]),而垂直錯(cuò)切參數(shù)通常對(duì)應(yīng)于矩陣的第二行第一列元素(M[1, 0])。
2.錯(cuò)切參數(shù)例子
????????以下是一個(gè)示例,說(shuō)明如何使用錯(cuò)切參數(shù)對(duì)對(duì)象進(jìn)行變形:
(1)水平錯(cuò)切
? ? ? ? 水平錯(cuò)切就是原圖每個(gè)像素的y不變,x根據(jù)M[0,1]進(jìn)行線性變換。
????????假設(shè)有一個(gè)矩形對(duì)象,原始的頂點(diǎn)坐標(biāo)為?(x1,?y1),?(x2,?y2),?(x3,?y3),?(x4,?y4)。要對(duì)該矩形進(jìn)行水平方向的錯(cuò)切變形,可以使用錯(cuò)切參數(shù)?shx,并將每個(gè)頂點(diǎn)的?x?坐標(biāo)按照如下方式進(jìn)行變換:
????????
????????這樣,通過(guò)調(diào)整?shx?的值,可以控制矩形在水平方向上的錯(cuò)切程度。
? ? ? ? 下面是水平錯(cuò)切的代碼和結(jié)果:
import cv2
import numpy as np
img_path = r'test.jpg'
target_path = r'test_1.jpg'
scale = 0.3 # 變換的比例
img = cv2.imread(img_path)
# 構(gòu)造錯(cuò)切變換矩陣
M = np.float32([[1, scale, 0], [0, 1, 0]])
h, w, _ = img.shape
img_shear = cv2.warpAffine(img, M, (w + int(scale * h), h))
cv2.imwrite(target_path, img_shear)
(2)垂直錯(cuò)切
? ? ? ? 垂直錯(cuò)切就是原圖每個(gè)像素的x不變,y根據(jù)M[1,0]進(jìn)行線性變換。
????????要對(duì)矩形進(jìn)行垂直方向的錯(cuò)切變形,可以使用錯(cuò)切參數(shù)?shy,并將每個(gè)頂點(diǎn)的?y?坐標(biāo)按照如下方式進(jìn)行變換:
????????通過(guò)調(diào)整?shy?的值,可以控制矩形在垂直方向上的錯(cuò)切程度。
????????下面是垂直錯(cuò)切的代碼和結(jié)果:
import cv2
import numpy as np
img_path = r'test.jpg'
target_path = r'test_2.jpg'
scale = 0.3 # 變換的比例
img = cv2.imread(img_path)
# 構(gòu)造錯(cuò)切變換矩陣
M = np.float32([[1, 0, 0], [scale, 1, 0]])
h, w, _ = img.shape
img_shear = cv2.warpAffine(img, M, (w, h + int(scale * w)))
cv2.imwrite(target_path, img_shear)
????????需要注意的是,錯(cuò)切參數(shù)的值可以是正數(shù)、負(fù)數(shù)或零,具體取決于所需的錯(cuò)切方向和程度。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-766971.html
????????cv2.estimateAffine2D 的原理就介紹到這里,關(guān)注不迷路(#^.^#)文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-766971.html
到了這里,關(guān)于【OpenCV】仿射變換中cv2.estimateAffine2D 的原理的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!