【特徴検出器】検出器

ここに画像の説明を挿入

1. シトマシ検出器

1.1 アルゴリズムの特徴:

  • Shi-Tomasi 検出器は、Harris アルゴリズムの改良版を使用します。これにより、画像エッジを処理する際のパフォーマンスが向上し、より安定したコーナーを検出できます。
  • Shi-Tomasi 検出器は、特徴点での共分散行列を計算し、それに対して固有値分解を実行することにより、各特徴点のコーナー応答関数を取得します。
  • Shi-Tomasi 検出器は、さまざまなアプリケーション シナリオに適応するために、しきい値を設定することで検出されるコーナーの数を制御できます。
  • Shi-Tomasi 検出器は、SIFT や SURF などの他のコーナー検出アルゴリズムよりも計算がはるかに高速であるため、リアルタイムのコンピューター ビジョン アプリケーションに適しています。

結論として、Shi-Tomasi 検出器は、高速、正確、制御可能なコーナー検出アルゴリズムとして、コンピューター ビジョンの分野で幅広い用途があります。

1.2 アルゴリズムのステップ

  1. ソーベル微分フィルターまたは他の勾配推定アルゴリズムを使用して、画像内の各ピクセルの x 方向と y 方向の勾配を計算します。

  2. 各ピクセルについて、2x2 局所自己相関行列 M を計算します。

M = ( ∑ x , y ∈ N ( I x ) 2 ∑ x , y ∈ NI x I y ∑ x , y ∈ NI x I y ∑ x , y ∈ N ( I y ) 2 ) , M=\begin{ pmatrix} \sum_{x,y\in N}(I_x)^2 & \sum_{x,y\in N}I_xI_y \\ \sum_{x,y\in N}I_xI_y & \sum_{x,y\ N}(I_y)^2 \end{pmatrix} において、M=(x , y N(×)2x , y N×はいx , y N×はいx , y N(はい)2)

このうち、N は現在のピクセルを中心とする近傍ウィンドウを表します。

  1. M の固有値 λ1 と λ2 を計算します。

  2. このピクセルがコーナーポイントであるかどうかを判断します。使用される方法は、λ1 と λ2 を組み合わせて応答関数 R を計算することです。

    一般的な応答関数には次のものがあります。

R = 最小 ( λ 1 , λ 2 ) R = λ 1 + λ 2 R = λ 1 λ 2 R = {\rm min}(\lambda_1, \lambda_2)\\ R = \lambda_1 + \lambda_2 \\ R = \frac{\lambda_1}{\lambda_2}R= l12)R=1+2R=21

通常、最初の関数はコーナー スコアの計算に使用され、すべてのピクセル ポイントのスコアが比較されてコーナー ポイントであるかどうかが判断されます。

  1. 非最大値抑制を実行して、繰り返されるコーナーを削除します。
  2. まず Shi-Tomasi コーナー検出を実行して、検出されたすべてのコーナーとその応答値 (キーポイント スコア) を取得します。
    各キー ポイントについて、その周囲の特定のサイズ (3x3 や 5x5 など) の近傍にあるすべてのキー ポイントの応答値を計算し、それらの中で最大の応答値を見つけて、この値を現在のキーの応答値と比較します。点。
    現在のキーポイントの応答値が最大でない場合、そのキーポイントは候補リストから削除されます。それ以外の場合は、ポイントを保持し、次のポイントまで処理を続行します。
bool compShiTomasiScore(const cv::Mat& img, const Eigen::Vector2i& px, double* score) {
    
    
  CHECK_NOTNULL(score);
  CHECK(img.type() == CV_8UC1);
  constexpr int kHalfPatchSize = 4;
  constexpr int kPatchSize = 2 * kHalfPatchSize;
  constexpr int kPatchArea = kPatchSize * kPatchSize;

  const int x_min = px(0) - kHalfPatchSize;
  const int x_max = px(0) + kHalfPatchSize;
  const int y_min = px(1) - kHalfPatchSize;
  const int y_max = px(1) + kHalfPatchSize;

  if (x_min < 1 || x_max >= img.cols - 1 || y_min < 1 || y_max >= img.rows - 1)
    return false;

  float dXX = 0.0;
  float dYY = 0.0;
  float dXY = 0.0;
  const int stride = img.step.p[0];
  for (int y = y_min; y < y_max; ++y) {
    
    
    const uint8_t* ptr_left = img.data + stride * y + x_min - 1;
    const uint8_t* ptr_right = img.data + stride * y + x_min + 1;
    const uint8_t* ptr_top = img.data + stride * (y - 1) + x_min;
    const uint8_t* ptr_bottom = img.data + stride * (y + 1) + x_min;
    for (int x = 0; x < kPatchSize; ++x, ++ptr_left, ++ptr_right, ++ptr_top, ++ptr_bottom) {
    
    
      float dx = *ptr_right - *ptr_left;
      float dy = *ptr_bottom - *ptr_top;
      dXX += dx * dx;
      dYY += dy * dy;
      dXY += dx * dy;
    }
  }

  // Find and return smaller eigenvalue:
  dXX = dXX / (2.0f * kPatchArea);
  dYY = dYY / (2.0f * kPatchArea);
  dXY = dXY / (2.0f * kPatchArea);
  *score = 0.5f * (dXX + dYY - std::sqrt((dXX - dYY) * (dXX - dYY) + 4 * dXY * dXY));
  return true;
}

これは Shi-Tomasi 検出器のアルゴリズム ステップであり、画像内の目立つコーナーを検出することで、特徴マッチングやオブジェクト追跡などのコンピューター ビジョン タスクに役立ちます。

1.3 8 近傍非最大抑制アルゴリズム

8 近傍非最大抑制アルゴリズム。非最大抑制はコンピュータ ビジョンで一般的に使用される手法で、画像内の冗長な特徴点を削除し、最も代表的な特徴点のみを保持するのに役立ちます。この関数は、入力スコア マップ スコアとコーナー グリッド グリッドに対して動作し、フィルター処理されたコーナー コーナーを出力します。

特定の実装では、関数はスコア マトリックスの各点をトラバースすることによって中心点 (center) とその周囲の 8 点 (p1 ~ p8) の座標を決定し、コーナー グリッド (k ) での位置を特定します。中心点のスコアが設定されたしきい値より小さい場合、直接スキップされます。それ以外の場合は、この点と周囲の点のスコア関係を確認し、非最大抑制の条件が満たされない場合はスキップします。スコアが他のポイントよりも高く、現在のコーナー ポイントのスコアよりも大きい場合は、コーナー ポイント情報を更新し、特にポイントの座標、スケール (つまり、ピラミッド レイヤーの数、レベル) を含むコーナー リストに追加します。 、スコア、角度、その他の情報。角度を計算するには getAngleAtPixelUsingHistogram() 関数を呼び出す必要があります。

非最大抑制プロセス全体が各ピラミッド レベルで 1 回実行され、さまざまなスケールで処理されて、よりグローバルなコーナー フィーチャが取得されます。

  // 8-neighbor nonmax suppression
  const int stride = score.step;
  for (int y = border; y < score.rows - border; ++y) {
    
    
    const float* p = &score.at<float>(y, border);
    for (int x = border; x < score.cols - border; ++x, ++p) {
    
    
      const int k = grid.getCellIndex(x, y, scale);
      if (grid.occupancy_.at(k))
        continue;

      const float* const center = p;
      if (*center < threshold)
        continue;
      if (*(center + 1) >= *center)
        continue;
      if (*(center - 1) > *center)
        continue;
      const float* const p1 = (center + stride);
      const
      float* const p2 = (center - stride);
      if (*p1 >= *center)
        continue;
      if (*p2 > *center)
        continue;
      if (*(p1 + 1) >= *center)
        continue;
      if (*(p1 - 1) > *center)
        continue;
      if (*(p2 + 1) >= *center)
        continue;
      if (*(p2 - 1) > *center)
        continue;

      Corner& c = corners.at(k);
      if (*p > c.score) {
    
    
        c.x = x * scale;
        c.y = y * scale;
        c.level = level - 1;
        c.score = *p;
        c.angle = getAngleAtPixelUsingHistogram(img_pyr[level], Eigen::Vector2i(x, y), 4);
      }
    }
  }

おすすめ

転載: blog.csdn.net/Darlingqiang/article/details/131324869