目錄
- 寫在前面
- 本文內容
- 1、影像的旋轉平移
- 二維xy坐標系
- 旋轉
- 影像坐標系
- 旋轉
- 旋轉平移
- 旋轉平移縮放
- 特殊情況
- 2、單應性變換
- 仿射變換
- 透視變換
- 3、opencv實驗
- 影像的旋轉平移縮放實作
- 代碼
- 不作任何變換
- 平移
- 平移+旋轉
- 仿射(用不同的縮放系數進行縮放)
- 透視
- 坐標系變換與影像坐標變換
- 完
寫在前面
1、文中所有資源、參考已給出來源鏈接,如有侵權請聯系洗掉
2、碼字不易,轉載本文請注明出處,本文鏈接:https://blog.csdn.net/qq_41102371/article/details/116245483
3、本文實驗環境:win10+vs2019+opencv440(vs2019配置opencv+contrib-440 + PCL1.10.0 + 原始碼單步除錯https://blog.csdn.net/qq_41102371/article/details/108727224)
本文內容
1、影像的旋轉平移原理及其實作
2、仿射變換及實體
3、透視變換及實體
4、opencv實驗結果
1、影像的旋轉平移
二維xy坐標系
如圖是以
O
O
O為原點的
x
y
xy
xy二維平面坐標系,平面上有一點
P
(
x
,
y
)
P(x, y)
P(x,y),與原點
O
O
O的距離
O
P
=
r
OP=r
OP=r,設
O
P
OP
OP與坐標軸x的夾角為
α
\alpha
α;
P
′
(
x
′
,
y
′
)
P'(x',y')
P′(x′,y′)是
P
P
P以
r
r
r為半徑以
O
O
O為圓心逆時針旋轉
β
\beta
β角度后得到的點

旋轉
現在用
P
P
P以及來表示
P
′
P'
P′
x
′
=
r
?
c
o
s
(
α
+
β
)
=
r
?
c
o
s
α
?
c
o
s
β
?
r
?
s
i
n
α
?
s
i
n
β
=
x
?
c
o
s
β
?
y
?
s
i
n
β
y
′
=
r
?
s
i
n
(
α
+
β
)
=
r
?
s
i
n
α
?
c
o
s
β
+
r
?
c
o
s
α
?
s
i
n
β
=
x
?
s
i
n
β
+
y
?
c
o
s
β
\begin{aligned} x'&=r*cos(\alpha+\beta)\\ &=r*cos\alpha * cos\beta-r*sin\alpha*sin\beta \\ &=x*cos\beta-y*sin\beta\\ y'&=r*sin(\alpha+\beta)\\ &=r*sin\alpha * cos\beta+r*cos\alpha*sin\beta \\ &=x*sin\beta+y*cos\beta \end{aligned}
x′y′?=r?cos(α+β)=r?cosα?cosβ?r?sinα?sinβ=x?cosβ?y?sinβ=r?sin(α+β)=r?sinα?cosβ+r?cosα?sinβ=x?sinβ+y?cosβ?
用矩陣表示:
[
x
′
y
′
]
=
[
c
o
s
β
?
s
i
n
β
s
i
n
β
c
o
s
β
]
[
x
y
]
\begin{bmatrix} x' \\ y' \end{bmatrix}= \begin{bmatrix} cos\beta & -sin\beta \\ sin\beta & cos\beta \end{bmatrix}\begin{bmatrix} x \\ y \end{bmatrix}
[x′y′?]=[cosβsinβ??sinβcosβ?][xy?]
以上推廣開來,二維平面上的點以坐標原點
O
O
O為中心,逆時針旋轉了
β
\beta
β度,
影像坐標系
首先看影像坐標系和二維xy坐標系

可以看到兩坐標系的橫軸
x
x
x與
u
u
u方向相同,縱軸
y
y
y與
v
v
v方向相反,上述的坐標公式表達是以二維xy坐標系的方向來思考的,那么在實際的影像坐標中:

旋轉
如圖是以
O
O
O為原點的
u
v
uv
uv影像平面坐標系,平面上有一點
P
(
x
,
y
)
P(x, y)
P(x,y),與原點
O
O
O的距離
O
P
=
r
OP=r
OP=r,設
O
P
OP
OP與坐標軸x的夾角為
α
\alpha
α;
P
′
(
x
′
,
y
′
)
P'(x',y')
P′(x′,y′)是
P
P
P以
r
r
r為半徑以
O
O
O為圓心逆時針旋轉
β
\beta
β角度后得到的點
x
′
=
r
?
c
o
s
(
α
?
β
)
=
r
?
c
o
s
α
?
c
o
s
β
+
r
?
s
i
n
α
?
s
i
n
β
=
x
?
c
o
s
β
+
y
?
s
i
n
β
y
′
=
r
?
s
i
n
(
α
?
β
)
=
r
?
s
i
n
α
?
c
o
s
β
?
r
?
c
o
s
α
?
s
i
n
β
=
?
x
?
s
i
n
β
+
y
?
c
o
s
β
\begin{aligned} x'&=r*cos(\alpha-\beta)\\ &=r*cos\alpha * cos\beta+r*sin\alpha*sin\beta \\ &=x*cos\beta+y*sin\beta\\ y'&=r*sin(\alpha-\beta)\\ &=r*sin\alpha * cos\beta-r*cos\alpha*sin\beta \\ &=-x*sin\beta+y*cos\beta \end{aligned}
x′y′?=r?cos(α?β)=r?cosα?cosβ+r?sinα?sinβ=x?cosβ+y?sinβ=r?sin(α?β)=r?sinα?cosβ?r?cosα?sinβ=?x?sinβ+y?cosβ?
用矩陣表示:
[
x
′
y
′
]
=
[
c
o
s
β
s
i
n
β
?
s
i
n
β
c
o
s
β
]
[
x
y
]
\begin{bmatrix} x' \\ y' \end{bmatrix}= \begin{bmatrix} cos\beta & sin\beta \\ -sin\beta & cos\beta \end{bmatrix}\begin{bmatrix} x \\ y \end{bmatrix}
[x′y′?]=[cosβ?sinβ?sinβcosβ?][xy?]
按照我們的常規思維,是希望影像繞著自己的中心旋轉一個角度的,但是影像
(
u
,
v
)
(u,v)
(u,v)坐標系和笛卡爾坐標系是不一樣的;下圖是影像的像素坐標系,每個方格代表一個像素,影像的行數為
r
o
w
s
rows
rows,列數為
c
o
l
s
cols
cols;影像坐標原點
O
O
O在左上角,不同于影像中心
(
u
0
,
v
0
)
=
(
c
o
l
s
/
2
,
r
o
w
s
/
2
)
(u_0,v_0)=(cols/2,rows/2)
(u0?,v0?)=(cols/2,rows/2),因此要減去影像中心
(
u
0
,
v
0
)
(u_0,v_0)
(u0?,v0?)讓影像中心移動到坐標原點上去,才能讓影像繞著自己的影像中心旋轉

因此
x
′
=
(
x
?
u
0
)
?
c
o
s
β
+
(
y
?
v
0
)
?
s
i
n
β
y
′
=
?
(
x
?
u
0
)
?
s
i
n
β
+
(
y
?
v
0
)
?
c
o
s
β
\begin{aligned}x'&=(x-u_0)*cos\beta+(y-v0)*sin\beta\\ y'&=-(x-u_0)*sin\beta+(y-v0)*cos\beta \end{aligned}
x′y′?=(x?u0?)?cosβ+(y?v0)?sinβ=?(x?u0?)?sinβ+(y?v0)?cosβ?
用矩陣表示:
[
x
′
y
′
]
=
[
c
o
s
β
s
i
n
β
?
s
i
n
β
c
o
s
β
]
[
x
?
u
0
y
?
v
0
]
\begin{bmatrix} x' \\ y' \end{bmatrix}= \begin{bmatrix} cos\beta & sin\beta \\ -sin\beta & cos\beta \end{bmatrix}\begin{bmatrix} x-u_0 \\ y-v_0 \end{bmatrix}
[x′y′?]=[cosβ?sinβ?sinβcosβ?][x?u0?y?v0??]
但是旋轉完成之后,我們得恢復影像中心,于是得加上之前減掉的
(
u
0
,
v
0
)
(u_0,v_0)
(u0?,v0?),
x
′
=
(
x
?
u
0
)
?
c
o
s
β
+
(
y
?
v
0
)
?
s
i
n
β
+
u
0
=
x
?
c
o
s
β
+
y
?
s
i
n
β
+
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
y
′
=
?
(
x
?
u
0
)
?
s
i
n
β
+
(
y
?
v
0
)
?
c
o
s
β
+
v
0
=
?
x
?
s
i
n
β
+
y
?
c
o
s
β
+
u
0
s
i
n
β
+
v
0
(
1
?
c
o
s
β
)
\begin{aligned} x' & = (x-u_0)*cos\beta+(y-v0)*sin\beta+u_0 \\ & = x*cos\beta+y*sin\beta+u_0(1-cos\beta)-v_0sin\beta\\ y' &=-(x-u_0)*sin\beta+(y-v0)*cos\beta+v_0\\ &=-x*sin\beta+y*cos\beta+u_0sin\beta+v_0(1-cos\beta) \end{aligned}
x′y′?=(x?u0?)?cosβ+(y?v0)?sinβ+u0?=x?cosβ+y?sinβ+u0?(1?cosβ)?v0?sinβ=?(x?u0?)?sinβ+(y?v0)?cosβ+v0?=?x?sinβ+y?cosβ+u0?sinβ+v0?(1?cosβ)?
齊次坐標矩陣表示:
[
x
′
y
′
1
]
=
[
c
o
s
β
s
i
n
β
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
?
s
i
n
β
c
o
s
β
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
0
0
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} cos\beta & sin\beta & u_0(1-cos\beta)-v_0sin\beta \\ -sin\beta & cos\beta &v_0(1-cos\beta)+u_0sin\beta\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
???x′y′1????=???cosβ?sinβ0?sinβcosβ0?u0?(1?cosβ)?v0?sinβv0?(1?cosβ)+u0?sinβ1???????xy1????
旋轉平移
我們可以再加上
(
u
1
,
v
1
)
(u_1,v_1)
(u1?,v1?)達到影像平移的效果
x
′
=
(
x
?
u
0
)
?
c
o
s
β
+
(
y
?
v
0
)
?
s
i
n
β
+
u
0
+
u
1
=
x
?
c
o
s
β
+
y
?
s
i
n
β
+
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
y
′
=
?
(
x
?
u
0
)
?
s
i
n
β
+
(
y
?
v
0
)
?
c
o
s
β
+
v
0
+
v
1
=
?
x
?
s
i
n
β
+
y
?
c
o
s
β
+
u
0
s
i
n
β
+
v
0
(
1
?
c
o
s
β
)
+
v
1
\begin{aligned} x' & = (x-u_0)*cos\beta+(y-v0)*sin\beta+u_0 +u_1\\ & = x*cos\beta+y*sin\beta+u_0(1-cos\beta)-v_0sin\beta+u_1\\ y' &=-(x-u_0)*sin\beta+(y-v0)*cos\beta+v_0+v_1\\ &=-x*sin\beta+y*cos\beta+u_0sin\beta+v_0(1-cos\beta)+v_1 \end{aligned}
x′y′?=(x?u0?)?cosβ+(y?v0)?sinβ+u0?+u1?=x?cosβ+y?sinβ+u0?(1?cosβ)?v0?sinβ+u1?=?(x?u0?)?sinβ+(y?v0)?cosβ+v0?+v1?=?x?sinβ+y?cosβ+u0?sinβ+v0?(1?cosβ)+v1??
矩陣表示:
[
x
′
y
′
1
]
=
[
c
o
s
β
s
i
n
β
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
?
s
i
n
β
c
o
s
β
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
+
v
1
0
0
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} cos\beta & sin\beta & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta & cos\beta &v_0(1-cos\beta)+u_0sin\beta+v_1\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
???x′y′1????=???cosβ?sinβ0?sinβcosβ0?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1???????xy1????
旋轉平移縮放
我們還可以在矩陣中乘以一個縮放系數
s
s
s對坐標進行縮放,達到影像縮放的目的
[
x
′
y
′
1
]
=
[
c
o
s
β
?
s
s
i
n
β
?
s
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
?
s
i
n
β
?
s
c
o
s
β
?
s
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
+
v
1
0
0
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} cos\beta*s & sin\beta *s & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s & cos\beta *s &v_0(1-cos\beta)+u_0sin\beta+v_1\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
???x′y′1????=???cosβ?s?sinβ?s0?sinβ?scosβ?s0?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1???????xy1????
特殊情況
當旋轉角度
β
=
0
\beta=0
β=0,平移量
(
u
1
,
v
1
)
=
(
0
,
0
)
(u_1,v_1)=(0,0)
(u1?,v1?)=(0,0),縮放系數
s
=
1
s=1
s=1時,相當于沒有對影像做變換,將上述引數帶入矩陣可得
[
x
′
y
′
1
]
=
[
1
0
0
0
1
0
0
0
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 &0\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
???x′y′1????=???100?010?001???????xy1????
可得:
x
′
=
x
y
′
=
y
x'=x\\ y'=y
x′=xy′=y
與實際一致
2、單應性變換
單應性主要針對的是影像中我們關心的目標區域處于同一平面,或者說目標處的起伏與相機到目標之間的距離比起來非常小,可以近似看成平面;在三維重建structure from motion中,如果兩幅影像之間的60%的特征點都滿足單應性,是不宜作為初始像對的,因為此時的特征點大多處于同一平面,對sfm來說是不好的;關于單應性變換的理解,可以閱讀這篇文章,講得很好:單應性Homograph估計:從傳統演算法到深度學習 https://zhuanlan.zhihu.com/p/74597564
仿射變換
對于上面的旋轉平移縮放矩陣,如果 x , y x,y x,y加以不同的縮放因子,比如 x , y x,y x,y軸的縮放因子分別是 s 1 , s 2 s_1,s_2 s1?,s2?
[ x ′ y ′ 1 ] = [ c o s β ? s 1 s i n β ? s 2 u 0 ( 1 ? c o s β ) ? v 0 s i n β + u 1 ? s i n β ? s 2 c o s β ? s 1 v 0 ( 1 ? c o s β ) + u 0 s i n β + v 1 0 0 1 ] [ x y 1 ] \begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} cos\beta*s1 & sin\beta *s2 & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s2 & cos\beta *s1 &v_0(1-cos\beta)+u_0sin\beta+v_1\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix} ???x′y′1????=???cosβ?s1?sinβ?s20?sinβ?s2cosβ?s10?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1???????xy1????
其中
H
=
[
h
11
h
12
h
13
h
21
h
22
h
23
h
31
h
32
h
33
]
=
[
c
o
s
β
?
s
1
s
i
n
β
?
s
2
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
?
s
i
n
β
?
s
2
c
o
s
β
?
s
1
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
+
v
1
0
0
1
]
H=\begin{bmatrix} h_{11} & h_{12} & h_{13}\\ h_{21} & h_{22} & h_{23}\\ h_{31} & h_{32} & h_{33} \end{bmatrix}= \begin{bmatrix} cos\beta*s1 & sin\beta *s2 & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s2 & cos\beta *s1 &v_0(1-cos\beta)+u_0sin\beta+v_1\\ 0&0&1 \end{bmatrix}
H=???h11?h21?h31??h12?h22?h32??h13?h23?h33?????=???cosβ?s1?sinβ?s20?sinβ?s2cosβ?s10?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1????
H
H
H就是一個仿射變換矩陣
透視變換
當上述 H H H矩陣的 h 31 , h 32 h_{31},h_{32} h31?,h32?不為0時, H H H是個透視變換矩陣
H = [ c o s β ? s 1 s i n β ? s 2 u 0 ( 1 ? c o s β ) ? v 0 s i n β + u 1 ? s i n β ? s 2 c o s β ? s 1 v 0 ( 1 ? c o s β ) + u 0 s i n β + v 1 k 1 k 2 1 ] H= \begin{bmatrix} cos\beta*s1 & sin\beta *s2 & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s2 & cos\beta *s1 &v_0(1-cos\beta)+u_0sin\beta+v_1\\ k_1&k_2&1 \end{bmatrix} H=???cosβ?s1?sinβ?s2k1??sinβ?s2cosβ?s1k2??u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1????
3、opencv實驗
首先看一段代碼:
\opencv-4.4.0\modules\imgproc\src\imgwarp.cpp
cv::Matx23d cv::getRotationMatrix2D_(Point2f center, double angle, double scale)
{
CV_INSTRUMENT_REGION();
angle *= CV_PI/180;
double alpha = std::cos(angle)*scale;
double beta = std::sin(angle)*scale;
Matx23d M(
alpha, beta, (1-alpha)*center.x - beta*center.y,
-beta, alpha, beta*center.x + (1-alpha)*center.y
);
return M;
}
這是opencv提供的獲取旋轉矩陣的函式,輸入是旋轉中心、角度、縮放系數,輸出是一個2x3的變換矩陣,對比上面的推導
[
x
′
y
′
1
]
=
[
c
o
s
β
?
s
s
i
n
β
?
s
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
?
s
i
n
β
?
s
c
o
s
β
?
s
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
+
v
1
0
0
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y'\\1 \end{bmatrix}= \begin{bmatrix} cos\beta*s & sin\beta *s & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s & cos\beta *s &v_0(1-cos\beta)+u_0sin\beta+v_1\\ 0&0&1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
???x′y′1????=???cosβ?s?sinβ?s0?sinβ?scosβ?s0?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1?1???????xy1????
[
x
′
y
′
]
=
[
c
o
s
β
?
s
s
i
n
β
?
s
u
0
(
1
?
c
o
s
β
)
?
v
0
s
i
n
β
+
u
1
?
s
i
n
β
?
s
c
o
s
β
?
s
v
0
(
1
?
c
o
s
β
)
+
u
0
s
i
n
β
+
v
1
]
[
x
y
1
]
\begin{bmatrix} x' \\ y' \end{bmatrix}= \begin{bmatrix} cos\beta*s & sin\beta *s & u_0(1-cos\beta)-v_0sin\beta+u_1 \\ -sin\beta *s & cos\beta *s &v_0(1-cos\beta)+u_0sin\beta+v_1 \end{bmatrix}\begin{bmatrix} x \\ y\\1 \end{bmatrix}
[x′y′?]=[cosβ?s?sinβ?s?sinβ?scosβ?s?u0?(1?cosβ)?v0?sinβ+u1?v0?(1?cosβ)+u0?sinβ+v1??]???xy1????
觀察代碼中的M矩陣,除了沒有加上平移量
(
u
1
,
v
!
)
(u_1,v_!)
(u1?,v!?),其余部分是完全對應的,此函式就是通過傳入旋轉中心、旋轉角度、縮放系數3個引數來計算出一個旋轉、縮放的變換矩陣;可能有人問那平移怎么實作呢,使用這個函式確實不能實作,下文會講到可以在獲取M矩陣后對其進行進一步的更改,
影像的旋轉平移縮放實作
代碼
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
template<typename T>
struct Scale_
{
T s1 = 1.0;
T s2 = 1.0;
T s3 = 1.0;
T s4 = 1.0;
};
template<typename T>
struct Perspective_
{
T p1 = 0;
T p2 = 0;
};
int main()
{
//讀入影像
cv::Mat srcImage;
srcImage = imread("data/rec.bmp", 1);
//srcImage = imread("data/graf3.png", 1);
//srcImage = imread("data/book1.jpg", 1);
if (!srcImage.data)
return -1;
imshow("srcImage", srcImage);
Mat destImage; //創建目標影像
double angle;//角度
Point2f translation;//平移量
Scale_<double> scale;//縮放系數
Perspective_<double> perspective;//透視變換
不作任何變換
//angle = 0;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//translation.x = 0;
//translation.y = 0;
//perspective.p1 = 0;
//perspective.p1 = 0;
平移
//angle = 0;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//translation.x = 50;
//translation.y = 100;
//perspective.p1 = 0;
//perspective.p1 = 0;
旋轉+平移
//angle = 45;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//scale.s1 = 1;
//translation.x = 50;
//translation.y = 100;
//perspective.p1 = 0;
//perspective.p1 = 0;
仿射(用不同的縮放系數進行縮放)
//angle = 45;
//scale.s1 = 1;
//scale.s1 = 0.5;
//scale.s1 = 0.3;
//scale.s1 = 0.75;
//translation.x = 0;
//translation.y = 0;
//perspective.p1 = 0;
//perspective.p1 = 0;
//透視
angle = 0;
scale.s1 = 1;
scale.s1 = 1;
scale.s1 = 1;
scale.s1 = 1;
translation.x = 0;
translation.y = 0;
//
perspective.p1 = 0.0006;
perspective.p2 = 0;
Point2f center(srcImage.cols / 2, srcImage.rows / 2);//中心
Mat M;
//由給定旋轉平移引數生成2x3的變換矩陣
//Mat getRotationMatrix2D(Point2f center, double angle, double scale)
M = getRotationMatrix2D(center, angle, 1);//計算旋轉的仿射變換矩陣
double v[1][3] = { 0,0,1 };
Mat row(1, 3, CV_64F, &v[0][0]); // 3 cols, 1 row
//將{0,0,1}添加至變換矩陣最后一行,使矩陣2x3的旋轉縮放矩陣變成3x3單應性矩陣
M.push_back(row);
//縮放
M.at<double>(0, 0) *= scale.s1; //h11
M.at<double>(0, 1) *= scale.s2; //h12
M.at<double>(1, 0) *= scale.s3; //h21
M.at<double>(1, 1) *= scale.s4; //h22
//平移
M.at<double>(0, 2) += translation.x; //h13
M.at<double>(1, 2) += translation.y; //h23
//透視
M.at<double>(2, 0) += perspective.p1; //h31
M.at<double>(2, 1) += perspective.p2; //h32
//使用變換矩陣對影像進行變換
warpPerspective(srcImage, destImage, M, Size(srcImage.cols, srcImage.rows));
//繪制旋轉中心
imwrite("output/graf3_trans.png", destImage);
imshow("dst", destImage);
waitKey(0);
return 0;
}
下面實驗結果,實驗使用的原圖(500x500)如下,除錯時查看mat的工具為image watch:opencv用VS2013除錯時用Image Watch插件查看圖片 https://blog.csdn.net/mao_hui_fei/article/details/80951075

不作任何變換
變換矩陣,可以看到此時變換矩陣為單位矩陣

變換結果

平移
變換矩陣,
h
13
h_{13}
h13?與
h
23
h_{23}
h23?是平移量

變換結果

平移+旋轉
變換矩陣

變換結果

仿射(用不同的縮放系數進行縮放)
變換矩陣

變換結果,可以看到矩形變成平行四邊形,圓形變橢圓

透視
變換矩陣

變換結果

變換矩陣

變換結果

坐標系變換與影像坐標變換
影像的旋轉平移是在同一坐標系下的坐標變換,為什么要加上同一坐標系下,因為得和坐標系變換作出區別
上述對影像的一系列操作,可以這樣想象:
將攝像頭固定,將影像列印至A4紙,把影像在空間中使用不同姿態、不同距離放置,每次拍照,便可得到上述變換的結果,比如上述的透視,像不像正對你的影像被側放了一個角度時的視覺效果,
而坐標系變換,可以這樣類比:
將列印的影像或目標物體放在固定的地方,用攝像機從不同距離、不同角度去拍攝目標,于是在多幅影像之間就涉及到了空間坐標系的變換以及多視圖幾何,
這兩種變換在進行公式推時候是有細微差別的,后面有空的話再寫一篇空間坐標系變換的文章聯系起來,
完
相比于出去人擠人汗流浹背,個人還是覺得躺家里睡覺舒服,不過今天白天著實睡太多了,不妥不妥,
各位勞動節快樂!
如有錯漏,敬請指正
--------------------------------------------------------------------------------------------諾有缸的高飛鳥202105
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/282615.html
標籤:其他
上一篇:Floyd
下一篇:計算機網路之網路分層結構
