SLAM への最初のエントリ (1) - ハリス コーナー検出

参照

https://blog.csdn.net/lbaihao/article/details/78919700
https://docs.opencv.org/4.x/dc/d0d/tutorial_py_features_harris.html

1 数学的導出

ハリスコーナー検出原理:

Harris アルゴリズムは、ウィンドウ内の灰色の画像の自己相関を使用してコーナー点を決定し、ウィンドウを設定して画像内を移動し、移動の前後でウィンドウが位置する領域の画像の自己相関係数を計算します。 。

ここに画像の説明を挿入
自己相関関数は次のように計算されます。(x, y) はウィンドウの中心位置、w(u, v) は重み (通常はガウス関数)、L はウィンドウを表し、(u, v) はウィンドウを表します。ウィンドウ内の画像の位置。
c ( x , y , Δ x , Δ y ) = ∑ ( u , v ) ∈ L w ( u , v ) ⋅ [ I ( u , v ) − I ( u + Δ x , v + Δ y ) ] 2 \mathrm{c}(\mathrm{x}, \mathrm{y}, \Delta \mathrm{x}, \Delta \mathrm{y})=\sum_{(\mathrm{u}, \mathrm{v} ) \in \mathrm{L}} \mathrm{w}(\mathrm{u}, \mathrm{v}) \cdot[\mathrm{I}(\mathrm{u}, \mathrm{v})-\ mathrm{I}(\mathrm{u}+\Delta \mathrm{x}, \mathrm{v}+\Delta \mathrm{y})]^{2}c ( x ,Δx _y ) _=( u , v ) Lw (あなたv )[あなたv )あなた+Δx _v+y ) ] _2. I ( u + Δ x , v + Δ y ) = I ( u , v ) + I x ( u , v ) ⋅ Δ x + I y ( u , v ) . ⋅ Δ y の微小関数 I とします

+ ⋯ + R n(u, v) ≈ I(u, v) + I x(u, v) ⋅ Δ x + I y(u, v) ⋅ Δ y {\color{Brown} \begin {array} {c} \mathrm{I}(\mathrm{u}+\Delta \mathrm{x}, \mathrm{v}+\Delta\mathrm{y})=\mathrm{I}(\mathrm{ u}, \mathrm{v})+\mathrm{I}_{\mathrm{x}}(\mathrm{u}, \mathrm{v}) \cdot \Delta \mathrm{x}+\mathrm{I }_{ \mathrm{y}}(\mathrm{u}, \mathrm{v}) \cdot \Delta \mathrm{y}+\cdots+\mathrm{R}_{\mathrm{n}}(\mathrm {u} , \mathrm{v}) \\\およそ \mathrm{I}(\mathrm{u}, \mathrm{v})+\mathrm{I}_{\mathrm{x}}(\mathrm{ u}, \mathrm{v}) \cdot \Delta \mathrm{x}+\mathrm{I}_{\mathrm{y}}(\mathrm{u}, \mathrm{v}) \cdot \Delta\ mathrm{y }\end{配列}}あなた+Δx _v+y ) _=あなたv )+×(あなたv )Δx_ _+はい(あなたv )y_ _++R(あなたv )あなたv )+×(あなたv )Δx_ _+はい(あなたv )y_ _
自己相関関数に代入すると、次のようになります。c ( x , y , Δ x , Δ y ) = ∑ ( u , v ) ϵ L w ( u , v ) ⋅ [ I ( u , v ) − I ( u + Δ x , v + Δ y ) ≈ ∑ ( u , v ) ∈ L w ( u , v ) ⋅ { I ( u , v ) − [ I ( u , v ) + I x ( u , v ) ⋅ Δ x + I y ( u , v ) ⋅ Δ y ] } 2 = ∑ ( u , v ) ∈ L w ( u , v ) [ I x ( u , v ) ⋅ Δ x + I y ( u , v ) ⋅ Δ y ] 2 \begin{aligned} \mathrm {c}(\mathrm{x}, \mathrm{y}, \Delta \mathrm{x}, \Delta\mathrm{y}) &=\sum_{(\mathrm{u}, \mathrm{v }) \epsilon \mathrm{L}} \mathrm{w}(\mathrm{u}, \mathrm{v}) \cdot[\mathrm{I}(\mathrm{u}, \mathrm{v})- \mathrm {I}(\mathrm{u}+\Delta \mathrm{x}, \mathrm{v}+\Delta\mathrm{y})]^{2} \\ & \about \sum_{(\mathrm {u }, \mathrm{v}) \in \mathrm{L}} \mathrm{w}(\mathrm{u}, \mathrm{v}) \cdot\left\{\mathrm{I}(\mathrm {u }, \mathrm{v})-\left[\mathrm{I}(\mathrm{u}, \mathrm{v})+\mathrm{I}_{\mathrm{x}}(\mathrm{ u} 、\mathrm{v}) \cdot \Delta \mathrm{x}+\mathrm{I}_{\mathrm{y}}(\mathrm{u}, \mathrm{v}) \cdot \Delta \mathrm{y }\right]\right\}^{2} \\ &=\sum_{(\maths{u}, \maths{v}) \in \maths{L}} \maths{w}(\maths{u }, \mathrm{v})\left[\mathrm{I}_{\mathrm{x}}(\mathrm{u}, \mathrm{v}) \cdot \Delta \mathrm{x}+\mathrm{ I}_{\mathrm{y}}(\mathrm{u}, \mathrm{v}) \cdot \Delta \mathrm{y}\right]^{2} \end{aligned}c ( x ,Δx _y ) _=( u , v ) ϵL _w (あなたv )[あなたv )あなた+Δx _v+y ) ] _2( u , v ) Lw (あなたv ){ (あなた,v )[あなたv )+×(あなたv )Δx_ _+はい(あなたv )y ] } _2=( u , v ) Lw (あなたv )[×(あなたv )Δx_ _+はい(あなたv )y ] _2
二乗項を展開して行列形式で書くと、次のようになります。
[ I x ( u , v ) ⋅ Δ x + I y ( u , v ) ⋅ Δ y ] 2 = I 2 x ( u , v ) Δ x 2 + I 2 y ( u , v ) Δ y 2 + 2 I x ( u , v ) I y ( u , v ) Δ x Δ y = I 2 x ( u , v ) Δ x 2 + I 2 y ( u , v ) Δ y 2 + 2 I x ( u , v ) I y ( u , v ) Δ x Δ y = [ I x 2 ( u , v ) Δ x + I x ( u , v ) I y ( u , v ) Δ y I y 2 ( u , v ) Δ y + I x ( u , v ) I y ( u , v ) Δ x ] ⋅ [ Δ x Δ y ] = [ Δ x Δ y ] ⋅ [ I x 2 ( u , v ) I x ( u , v ) I y ( u , v ) I x ( u , v ) I y ( u , v ) I y 2 ( u , v ) ] ⋅ [ Δ x Δ y ] \begin{array}{l} {\left[I_ {x}(u, v) \cdot \Delta x+I_{y}(u, v) \cdot \Delta y\right]^{2}} \\ =I^{2}{ }_{x} (u, v) \デルタ x^{2}+I^{2}{ }_{y}(u, v) \デルタ y^{2}+2 I_{x}(u, v) I_{y }(u, v) \デルタ x \デルタ y \\ =I^{2}{ }_{x}(u, v) \デルタ x^{2}+I^{2}{ }_{y} (u, v) \Delta y^{2}+2 I_{x}(u, v) I_{y}(u, v) \Delta x \Delta y \\ =\left[\begin{array}{ lc} I_{x}^{2}(u, v) \デルタ x+I_{x}(u,v) I_{y}(u, v) \Delta y & I_{y}^{2}(u, v) \Delta y+I_{x}(u, v) I_{y}(u, v) \Delta x \end{array}\right] \cdot\left[\begin{array}{l} \Delta x \\ \Delta y \end{array}\right] \\ =\left[\begin{array }{ll} \Delta x & \Delta y \end{array}\right] \cdot\left[\begin{array}{cc} I_{x}^{2}(u, v) & I_{x} (u, v) I_{y}(u, v) \\ I_{x}(u, v) I_{y}(u, v) & I_{y}^{2}(u, v) \end {配列}\right] \cdot\left[\begin{配列}{l} \Delta x \\ \Delta y \end{array}\right] \end{array}v) \end{array}\right] \cdot\left[\begin{array}{l} \Delta x \\ \Delta y \end{array}\right] \end{array}v) \end{array}\right] \cdot\left[\begin{array}{l} \Delta x \\ \Delta y \end{array}\right] \end{array}[×(あなたv )Δx_ _+はい(あなたv )y ] _2=2×(あなたv ) Δ x2+2はい(あなたv ) Δ y2+2×(あなたv )はい(あなたv ) Δ x Δ y=2×(あなたv ) Δ x2+2はい(あなたv ) Δ y2+2×(あなたv )はい(あなたv ) Δ x Δ y=[バツ2(あなたv ) Δ x+×(あなたv )はい(あなたv ) Δ yy2(あなたv ) Δ y+×(あなたv )はい(あなたv ) Δ x[Δx_ _y_ _=[Δ ×y_ _[バツ2(あなたv )×(あなたv )はい(あなたv )×(あなたv )はい(あなたv )y2(あなたv )[Δx_ _y_ _]

自己相関関数に代入すると、次のようになります。
v) \cdot \Delta x+I_{y}(u, v) \cdot \Delta y\right]^{2}\\ \\ =\sum_{(u, v) \in L} w(x, y)\left[I^{2}{ }_{x}(u, v) \Delta x^{2}+I^{2}{ }_{y}(u, v) \Delta y^{ 2}\そうです。\left.+2 I_{x}(u, v) I_{y}(u, v) \Delta x \Delta y\right]\\ \\ =\sum_{(u, v) \in L} w (x, y)\left[\begin{array}{ll} \Delta x & \Delta y \end{array}\right]\left[\begin{array}{cc} I_{x}^{2} (u, v) & I_{x}(u, v) I_{y}(u, v) \\ I_{x}(u, v) I_{y}(u, v) & I_{y}^ {2}(u, v) \end{array}\right]\left[\begin{array}{l} \Delta x \\ \Delta y \end{array}\right]\\ \\ =\left [\begin{array}{ll} \Delta x & \Delta y \end{array}\right]\left\{\sum_{(u, v) \in L} w(x, y)\left[\ begin{array}{cc} I_{x}^{2}(u, v) & I_{x}(u, v) I_{y}(u, v) \\ I_{x}(u, v) I_{y}(u, v) & I_{y}^{2}(u,c ( x ,Δx _y ) _( u , v ) Lw ( x ,y [×(あなたv )Δx_ _+はい(あなたv )y ] _2=( u , v ) Lw ( x ,y [2×(あなたv ) Δ x2+2はい(あなたv ) Δ y2+ 2I _×(あなたv )はい(あなたv ) Δ x Δ y ]=( u , v ) Lw ( x ,y [Δ ×y_ _[バツ2(あなたv )×(あなたv )はい(あなたv )×(あなたv )はい(あなたv )y2(あなたv )[Δx_ _y_ _=[Δ ×y_ _{ ( u , v ) Lw ( x ,y [バツ2(あなたv )×(あなたv )はい(あなたv )×(あなたv )はい(あなたv )y2(あなたv )] }[Δx_ _y_ _=[Δ ×y_ _[( u , v ) ϵL _バツ2(あなたv )( u , v ) L×(あなたv )はい(あなたv )( u , v ) ϵL _×(あなたv )はい(あなたv )( u , v ) ϵL _y2(あなたv )[Δx_ _y_ _=[Δ ×y_ _[CCB[Δx_ _y_ _]

従属変数を決定します:
c ( x , y , Δ x , Δ y ) = [ Δ x Δ y ] ⋅ M ⋅ [ Δ x Δ y ] {\color{Red} \begin{array}{l} c (x , y, \Delta x, \Delta y) =\left[\begin{array}{ll} \Delta x & \Delta y \end{array}\right] \cdot M \cdot\left[\begin {array }{l} \デルタ x\\\デルタ y \end{配列}\right] \end{配列}}c ( x ,Δx _y ) _=[Δ ×y_ _M[Δx_ _y_ _]
M = ∑ x , yw ( x , y ) [ I x I x I x I y I x I y I y I y ] M = \sum_{x,y} w(x,y) \begin{bmatrix}I_x I_x & I_x I_y \\ I_x I_y & I_y I_y \end{bmatrix}M=x yw ( x ,y [×××はい×はいはいはい]
这里 I x I_x × I y I_y はい画像の x 方向と y 方向の画像導関数です (cv2.Sobel() を使用して簡単に取得できます)。

楕円の方程式

ここに画像の説明を挿入
x 2 a 2 + y 2 b 2 = 1 \frac{x^{2}}{a^{2}}+\frac{y^{2}}{b^{2}}=1ある2バツ2+b2y2=1
マス阵表达:
[ xy ] [ 1 a 2 0 0 1 b 2 ] [ xy ] = 1 \left[\begin{array}{ll} x & y \end{array}\right]\left[\begin{配列}{ll} \frac{1}{a^{2}} & 0 \\ 0 & \frac{1}{b^{2}} \end{配列}\right]\left[\begin{配列{l} x \\ y \end{配列}\right]=1[×はい[ある2100b21[バツはい=1
nxn 行列はその固有値を解くことができます。上記の中間行列の固有値を解くと、
{ λ 1 = 1 a 2 λ 2 = 1 b 2 { a = 1 λ 1 b = 1 λ 2 \left\ {\begin{array} { l } { \lambda _ { 1 } = \frac { 1 } { a ^ { 2 } } } \\ { \lambda _ { 2 } = \frac { 1 } { b ^ { 2 } } } \end{array} \quad \left\{\begin{array}{l} a=\frac{1}{\sqrt{\lambda_{1}}} \\ b=\frac {1}{ \sqrt{\lambda_{2}}} \end{配列}\right.\right.{ 1=ある212=b21{ ある=1 1b=2 1
固有値が大きいほど、軸半径は短くなります。

M行列

c ( x , y , Δ x , Δ y ) = [ Δ x Δ y ] ⋅ M ⋅ [ Δ x Δ y ] {\color{Red} \begin{array}{l} c(x, y, \Delta x, \Delta y) =\left[\begin{array}{ll} \Delta x & \Delta y \end{array}\right] \cdot M \cdot\left[\begin{array}{l} \デルタ x \\ \デルタ y \end{配列}\right] \end{配列}}c ( x ,Δx _y ) _=[Δ ×y_ _M[Δx_ _y_ _]
M = ∑ x , yw ( x , y ) [ I x I x I x I y I x I y I y I y ] M = \sum_{x,y} w(x,y) \begin{bmatrix}I_x I_x & I_x I_y \\ I_x I_y & I_y I_y \end{bmatrix}M=x yw ( x ,y [×××はい×はいはいはい]
自己相関関数が実際には楕円の行列表現であることがわかりました。
次に、MM をM行列λ 1 \lambda_11λ 2 \lambda_22

  1. λ 1 \lambda_11λ 2 \lambda_22は非常に小さく、軸の長さは長いため、点が平らな領域にあることを意味します。
  2. λ 1 \lambda_11λ 2 \lambda_22それらはすべて非常に大きく、互いに比較的近く、軸の長さが非常に小さいため、コーナー ポイントと見なすことができます。
  3. λ 1 \lambda_11λ 2 \lambda_22そのうちの 1 つは非常に小さく、1 つは非常に大きく、1 つの軸は長く、もう 1 つの軸は短く、現時点ではエッジ領域と考えることができます。
    ここに画像の説明を挿入

上記の方法に従うと、点ごとに多くのことを計算する必要があることは明らかであり、速度が遅すぎるため、経験式を提案します。
R = det ( M ) − k ( トレース ( M ) ) 2 R=det(M)-k(trace(M))^2R=デット( M ) _ _k (トレース( M ) ) _ _ _
そのうち2つ、

  • der ( M ) = λ 1 ⋅ λ 2 = AB − C 2 der(M)=\lambda_1\cdot\lambda_2=AB-C^2( M ) _=12=AB _C2
  • トレース ( M ) = λ 1 + λ 2 = A + B トレース(M)=\lambda_1+\lambda_2=A+Bトレース( M ) _ _ _=1+2=+B
  • λ 1 \lambda_11λ 2 \lambda_22MMですMの固有値
  • kkkは経験値で、通常は 0.02 ~ 0.04 です。

2 OpenCVの実装

2.1 関数 cv2.cornerHarris() [ざっくり理解]

2.1.1 パラメータ

  • img: 入力画像。float32 グレースケール画像である必要があります。
  • blockSize: コーナー検出で考慮される領域のサイズ
  • ksize: ソーベル導関数を使用した開口パラメータ
  • k: ハリス検出スコアRRRkkkのパラメータ値
# -*-coding:utf-8-*-
import numpy as np
import cv2

filename = '1.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

# opencv需要输入是float32类型的
gray = np.float32(gray)
# 返回值是一个跟图片同样大小的矩阵分数图
dst = cv2.cornerHarris(gray, 5, 3, 0.04)

# 通过图像自身的分数图的大小关系,得到哪些像素点应该是角点,
# 这些像素点的值都变为[0,0,255],也就是红色。
img[dst>0.01*dst.max()]=[0,0,255]
cv2.imshow('dst', img)
cv2.waitKey(0)

ここに画像の説明を挿入ここに画像の説明を挿入

2.2 cv2.goodFeatureToTrack()

上記の API の問題は、返されるのがコーナー点の位置座標ではなくスコア マップであり、ソース画像をスコア マップで直接処理していることです。
cv2.goodFeatureToTrack() は、Harris コーナー検出をサポートするだけでなく、Shi Tomasi アルゴリズムのコーナー検出もサポートします。

2.2.1 パラメータ

  • grey_src: 8 ビットまたは 32 ビットのシングルチャネル グレースケール イメージ
  • コーナー: 位置点ベクトル。検出されたコーナー点の座標を保存します。
  • max_corners: 検出できるコーナーポイントの最大数として定義されます。
  • qualityLevel: 検出されたコーナーポイントの品質レベル、および固有値がqualityLevelの最大固有値未満のポイントは破棄されます。
  • minDistance: 2 つのコーナーポイント間の最小距離 (ピクセル単位)。
  • マスク: 検出領域を指定します。画像全体が検出された場合、マスクは空になります。
  • blockSize: 自己相関関数の共分散行列のウィンドウ サイズを計算します。
  • useHarrisDetector: Harris コーナー検出を使用するかどうか。false の場合は Shi-Tomasi 演算子を使用します。
  • k: Harris コーナー検出のハイパーパラメータ、通常は 0.02 ~ 0.04、userHarrisDetector が false の場合、機能しません。
# -*-coding:utf-8-*-
import numpy as np
import cv2

filename = '1.jpg'
img = cv2.imread(filename)
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

gray = np.float32(gray)


corners = cv2.goodFeaturesToTrack(gray, maxCorners=1000, qualityLevel=0.01, minDistance=10)
corners = np.int0(corners)
for i in corners:
    x,y = i.ravel()
    cv2.circle(img, (x, y), 2, (0, 0, 255), -1)

cv2.imshow('out.jpg', img)

cv2.waitKey(0)


ここに画像の説明を挿入ここに画像の説明を挿入

サブピクセル

cv2.cornerSubPix()

パラメータ:

  • 画像: 入​​力画像
  • コーナー: コーナーポイントの初期座標を入力します。
  • winSize: 検索ウィンドウの辺の長さの半分。winSize=(5,5) の場合、 (5 2+1) (5 2+1)=11 11 のサイズの検索ウィンドウが使用されます。
  • zeroZone: 検索エリアの中央にあるデッド領域の辺の長さの半分。値が (-1, -1) に設定されている場合は、そのような領域が存在しないことを意味します。
  • cirteria: コーナーポイント精度の反復プロセスの終了条件。通常はcriteria = ( cv 2. Term C riteria EPS + cv 2. Term C riteria MAXITER , 100 , 0.001 ) criteria = (cv2.TermCriteria_EPS + cv2.TermCriteria_MAX_ITER, ) を使用します。 100、0.001)基準_ _ _ _=( c v 2.期間基準_ _ _ _ _ _ _ _EPS+c v 2.期間基準_ _ _ _ _ _ _ _M× _TER 100 0.001 )

おすすめ

転載: blog.csdn.net/REstrat/article/details/127023553