[300 OpenCV ルーチン] 245. 特徴検出のための BRISK 演算子

「youcansのOpenCVルーチン300個 - 総合カタログ」


[youcansのOpenCVルーチン300個] 245. 特徴検出のためのBRISK演算子


6.8.1 アルゴリズムの紹介

スケール不変バイナリ機能記述 BRISK (Binary Robust Invariant Scalable Kepoints) は、改良された Brief アルゴリズムであり、バイナリ機能記述子です。高い計算効率、回転不変性、スケール不変性、およびノイズに対するロバスト性を備えています。

1.スケールスペースを確立する

スケールの不変性を実現するために、BRISK アルゴリズムは、画像ピラミッドを構築することによって各キーポイントのスケールを取得します。BRISK アルゴリズムの画像ピラミッドは、n レベルのオクターブと n レベルのイントラ オクターブで構成されます。オクターブの上位レベルのイメージは下位レベルのイメージをダウンサンプリングすることによって得られ、内側のオクターブは隣接するオクターブの間に位置します。

画像 c0 d0 c1 d1 c2 d2 c3 d3
高い 時間 2/3*時間 1/2*時間 1/3*時間 1/4*時間 1/6*時間 1/8*時間 1/12*時間
2/3*インチ 1/2 *インチ 1/3*インチ 1/4*インチ 1/6*インチ 1/8*インチ 1/12*インチ

2. キーポイント検出

SIFT アルゴリズムと同様に、キーポイント検出には、スケール空間コーナー検出、非最大抑制、およびサブピクセル補間の 3 つのステップが含まれます。

(1) コーナー検出には AGAST 法の FAST9-16 検出器と FAST5-8 検出器を使用します。FAST5-8 を使用して元の画像 img のコーナーを d(-1) 層として検出し、FAST9-16 を使用して画像 c0~c3 および d0~d3 のコーナーを検出します。合計9枚のコーナー点検出画像が得られる。

(2) 3*3*3 近傍で非最大抑制を実行して、空間位置とスケール空間で局所的な特徴点を特定します。近傍の 26 点(隣接する同スケールの 8 点と隣接する上下のスケールに対応する 9*2 点)と画素点を比較し、最大値・最小値の場合は画素値として確保キーポイント。

(3) 正確な位置決めのためにサブピクセル補間を使用します。非最大抑制によって得られた極値点は、スケール空間とピクセル空間で離散的であり、得られた極値点の位置とスケール サイズの精度は低くなります。

最初に、FAST スコア値に従ってピクセル空間で 2 次元二次関数補間を実行してキー ポイントの正確な座標位置を取得し、次にスケール方向で 1 次元補間を実行してキー ポイントの正確なスケールを取得します。

3. サンプリングモードと主方向

BRISK 記述子の鍵は、キーポイント近傍のサンプリング パターンです。図に示すように、特徴点(キーポイント)を中心としたS*S領域でN点をサンプリングし、N * ( N − 1 ) / 2 N * (N-1)/2を形成します。N( N1 ) /2組のサンプル点(pi, pj) (p_i, p_j)( pp


ここに画像の説明を挿入

画像のエイリアシングを避けるため、サンプリング ポイント P の分散はσ \sigmaです。σ、分散σ \sigmaσは、サンプリング ポイントから中心までの距離 r に比例します。

次に、局所勾配値を計算します:
g ( pi , pj ) = ( pj − pi ) ∗ I ( pj , σ j ) − I ( pi , σ i ) ∣ ∣ pj − pi ∣ ∣ 2 g(p_i, p_j) = ( p_j - p_i)* \frac{I(p_j,\sigma_j) - I(p_i,\sigma_i)}{||p_j - p_i||^2}g ( pp)=( pp)∣∣ pp2( pp)( pp)
其中, g ( p i , p j ) g(p_i, p_j) g ( pp)は、ローカル勾配値を表しますI ( pj , σ j ) I(p_j,\sigma_j)( pp)はピクセル値pppはキー ポイントの位置、σ \sigmaσはキーポイント スケールです。

すべてのサンプル ポイントのペアを考慮すると、短距離のしきい値δ max = 9.75 ∗ t \delta_{max}=9.75*tdマックス_=9.75tと長距離しきい値δ min = 13.67 ∗ t \delta_{min}=13.67*td=13.67t (t は特徴点のスケール k)、近距離点ペアのサブセット S と遠距離点ペアのサブセット L が取得されます。

キーポイントの主方向は、局所勾配値から計算できます:
g = ( gxgy ) = 1 L ∗ ∑ ( pi , pj ) ∈ L g ( pi , pj ) g = \binom{g_x}{g_y} = \frac {1 }{L}*\sum_{(pi,pj) \in L} g(p_i,p_j)g=(gg×)=L1( p i , p j ) Lg ( pp)
特徴点を中心にサンプリング領域を主方向に回転します。回転角度はα = arctan 2 ( gy , gx ) \alpha=arctan2(g_y, g_x)a=a rc t an 2 ( gg×)、こうして回転不変性を達成します。

4. バイナリ特徴記述子

BRISK ディスクリプタはバイナリ機能であり、ディスクリプタの各ビットは近距離ポイント ペアの比較結果に対応します:
b = { 1 , I ( pj α , σ j ) > I ( pi α , σ i ) 0 , elseb =\begin{cases} 1 &, I(p_j^\alpha,\sigma_j) > I(p_i^\alpha,\sigma_i)\\ 0&, else \end{cases}b={ 10( pjap)>( pap)エルセ_ _
N を 60 とすると、合計 1770 点のペアがあります。512 ビットのバイナリ コード、つまり 64 バイトを構成する 512 の近距離ポイント ツー ポイント ペアを考えてみましょう。

BRISK アルゴリズムは、バイナリ文字列の特徴記述方法を直接生成します。これにより、特徴記述子の確立が高速化され、特徴記述子のメモリ使用量と特徴マッチングの時間が大幅に削減されます。

4. 特徴マッチング

ハミング距離を用いた特徴点マッチング。

画像登録テストの速度比較:SIFT<SURF<BRISK<FREAK<ORB. BRISK アルゴリズムは、ぼやけが大きいイメージ レジストレーションに最適です。


6.8.2 OpenCV の BRISK クラス

OpenCV は豊富な機能検出アルゴリズムを提供し、統一された定義とカプセル化を使用して cv::Feature2D クラスを継承します。

OpenCV は、cv::BRISK クラスを提供して BRISK メソッドを実装し、cv::Feature2D クラスを継承し、create static メソッドを通じて作成します。

BriefDescriptorExtractor クラスのコンストラクタには、次の 3 つの形式があります。

BRISK::BRISK()
static Ptr< BRISK > create (int thresh=30, int octaves=3, float patternScale=1.0f)
static Ptr< BRISK > create (const std::vector< float > &radiusList, const std::vector< int > &numberList, float dMax=5.85f, float dMin=8.2f, const std::vector< int > &indexChange=std::vector< int >()))
static Ptr< BRISK > create (int thresh, int octaves, const std::vector< float > &radiusList, const std::vector< int > &numberList, float dMax=5.85f, float dMin=8.2f, const std::vector< int > &indexChange=std::vector< int >())

Python 言語では、OpenCV はインターフェイス関数cv.BRISK.create()を提供して、BRISK クラスをインスタンス化します。

cv.BRISK.create([, thresh=30, octaves=3, patternScale=1.0f]) → retval
cv.BRISK.create(radiusList, numberList[, dMax=5.85f, dMin=8.2f, indexChange=std::vector<int>()]) → retval

cv.BRISK.create(thresh, octaves, radiusList, numberList[, dMax=5.85f, dMin=8.2f, indexChange=std::vector<int>()]) → retval
cv.BRISK_create([, thresh=30, octaves=3, patternScale=1.0f]	) → retval

cv.BRISK_create(radiusList, numberList[, dMax=5.85f, dMin=8.2f, indexChange=std::vector<int>()]) → retval
cv.BRISK_create(thresh, octaves, radiusList, numberList[, dMax=5.85f, dMin=8.2f, indexChange=std::vector<int>()]) → retval

brisk.compute(image, keypoints[, descriptors=None]) → keypoints, descriptors

パラメータの説明:

  • image: 入力画像、シングルチャンネル

  • thresh: AGGST 検出しきい値

  • octaves: オクターブ、0 はシングル スケールを意味します

  • patternScale: キーポイントの近傍をサンプリングするために使用されるパターン スケール

  • radiusList: キーポイントの周囲のサンプリング半径 (単位はピクセル、スケールは 1)

  • numberList: 円周上のサンプリング ポイントの数を定義します。長さは radiusList と同じです。

  • dMax: 短いペアリングのしきい値 (ピクセル単位、スケール 1)

  • dMin: 長いペアリングのしきい値 (単位はピクセル、スケールは 1)

  • indexChange: ビットの再マッピングのインデックス

  • keypoints : 検出されたキーポイント、特別なデータ構造

  • 記述子: キー ポイントの記述子、Numpy 配列、形状 (n、バイト)


ルーチン 14.27: 特徴検出のための BRISK 演算子

    # 14.27 特征检测之 BRISK 算子
    # 读取基准图像
    imgRef = cv.imread("../images/Circuit04.png", flags=1)  # (480, 600, 3)
    refer = cv.cvtColor(imgRef, cv.COLOR_BGR2GRAY)  # 基准图像
    height, width = imgRef.shape[:2]  # 图片的高度和宽度
    print("shape of image: ", height, width)
    # 读取或构造目标图像
    top, left = int(0.1*height), int(0.1*width)
    border = cv.copyMakeBorder(imgRef, top, top, left, top, borderType=cv.BORDER_CONSTANT, value=(32,32,32))
    zoom = cv.resize(border, (width, height), interpolation=cv.INTER_AREA)
    theta= 15  # 顺时针旋转角度,单位为角度
    x0, y0 = width//2, height//2  # 以图像中心作为旋转中心
    MAR = cv.getRotationMatrix2D((x0,y0), theta, 1.0)
    imgObj = cv.warpAffine(zoom, MAR, (width, height))  # 旋转变换,默认为黑色填充
    # imgObj = cv.imread("../images/Circuit04B.png", flags=1)  # (480, 600, 3)
    object = cv.cvtColor(imgObj, cv.COLOR_BGR2GRAY)  # 目标图像
    print("shape of image: ", imgObj.shape)

    # 构造 BRISK 对象,检测关键点,计算特征描述向量
    brisk = cv.BRISK_create()  # 创建 BRISK 检测器
    kpRef, desRef = brisk.detectAndCompute(refer, None)  # 基准图像关键点检测
    kpObj, desObj = brisk.detectAndCompute(object, None)  # 目标图像关键点检测
    imgRefBrisk = cv.drawKeypoints(imgRef, kpRef, None, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)  # 绘制关键点大小和方向
    imgObjBrisk = cv.drawKeypoints(imgObj, kpObj, None, flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)  # 绘制关键点大小和方向
    print(desRef.shape, desObj.shape)

    # 特征点匹配,Brute-force matcher
    matcher = cv.BFMatcher()  # 构造 BFmatcher 对象
    matches = matcher.match(desRef, desObj)  # 对描述子 des1, des2 进行匹配
    matches = sorted(matches, key=lambda x: x.distance)
    matches1 = cv.drawMatches(imgRef, kpRef, imgObj, kpObj, matches[:100], None, flags=2)
    print('queryIdx=%d' % matches[0].queryIdx)
    print('trainIdx=%d' % matches[0].trainIdx)
    print('distance=%d' % matches[0].distance)
    print("bf.match:{}".format(len(matches)))

    plt.figure(figsize=(9, 6))
    ax1 = plt.subplot(212)
    ax1.set_title("BRISK detector & BFMatcher")
    plt.imshow(cv.cvtColor(matches1, cv.COLOR_BGR2RGB)), plt.axis('off')
    ax2 = plt.subplot(221)
    plt.axis('off'), plt.imshow(cv.cvtColor(imgRefBrisk, cv.COLOR_BGR2RGB))
    ax2.set_title("BRISK keypoints (Ref)")
    ax3 = plt.subplot(222)
    plt.axis('off'), plt.imshow(cv.cvtColor(imgObjBrisk, cv.COLOR_BGR2RGB))
    ax3.set_title("BRISK keypoints (Obj)")
    plt.tight_layout()
    plt.show()

ここに画像の説明を挿入



参考文献:ステファン・ロイテネッガー、マルガリータ・チリ、ローランド・イヴ・ジークヴァルト. Brisk: バイナリ ロバスト インバリアント スケーラブル キーポイント。Computer Vision (ICCV)、2011 IEEE International Conference onページ 2548–2555。IEEE、2011年。

ここに画像の説明を挿入

【本節終了】

著作権表示:
youcans@xupt オリジナル作品、転載には元のリンクを記載する必要があります: (https://blog.csdn.net/youcans/article/details/127415464)
Copyright 2022 youcans, XUPT Crated
: 2022-10-20

241. スケール不変特徴変換 (SIFT)
242. 加速ロバスト特徴検出アルゴリズム (SURF)
243. 特徴検出のための FAST アルゴリズム

おすすめ

転載: blog.csdn.net/youcans/article/details/127415464