画像の特徴点検出アルゴリズム比較実験

はじめに

本記事では、画像処理における特徴点検出について解説します。特徴点検出は、画像内で際立った特徴を持つ点を特定する技術であり、画像マッチング、物体認識、画像位置合わせなど、様々な応用分野で重要な役割を果たします。

この記事を書いたひと

デジタルリアクタ合同会社 代表
機械学習・統計、数値計算などの領域を軸としたソフトウェアエンジニアリングを専門としています。スタートアップからグローバル企業まで、さまざまなスケールの企業にて、事業価値に直結する計算システムを設計・構築してきました。主に機械学習の応用分野において、出版・発表、特許取得等の実績があり、また、IT戦略やデータベース技術等の情報処理に関する専門領域の国家資格を複数保有しています。九州大学理学部卒業。日本ITストラテジスト協会正会員。

本記事では、代表的な特徴点検出アルゴリズムであるSIFT、KAZE、AKAZE、ORB、BRISK、FREAKを実装し、それぞれの特性を比較します。

対象読者:

  • 画像処理の基礎を理解している方
  • 特徴点検出アルゴリズムの選択に関心のある方
  • OpenCVを用いたPythonプログラミングの経験がある方

記事のポイント:

  • 各特徴点検出アルゴリズムの理論的な背景を解説
  • OpenCVを用いたPythonによる実装例を提示
  • 実際の画像を用いた実験結果を比較
  • 各アルゴリズムの長所と短所、使い分けについて考察

ライセンスと特許について

特徴点検出アルゴリズムを実務で使用する際は、ライセンスや特許の状況を確認することが重要です。

アルゴリズム ライセンス 特許状況
SIFT 2020年3月に失効、現在は自由に使用可能
KAZE BSDライセンス 商用利用も自由
AKAZE BSDライセンス 商用利用も自由
ORB BSDライセンス 商用利用も自由
BRISK BSDライセンス 商用利用も自由
FREAK BSDライセンス 商用利用も自由

商用利用を検討している場合、上記のアルゴリズムはすべて自由に使用できます。今回は比較しませんが、比較対象によく上がるSURFは現在も商用利用にはライセンス費用を支払う必要があります。

理論的背景

ここでは、各アルゴリズムの理論的な背景について解説します。各アルゴリズムがどのような原理に基づいて特徴点を検出しているのかを理解することで、アルゴリズム選択の際の判断材料とすることができます。

SIFT (Scale-Invariant Feature Transform)

SIFTは、スケール空間でのガウシアン差分(DoG: Difference of Gaussian)を利用して特徴点を検出します。スケール空間とは、画像に対して異なる大きさのガウシアンフィルタを適用することで得られる空間です。このスケール空間を用いることで、画像のスケール変化に対してロバスト(頑健)な特徴点検出が可能になります。

DoGは以下の式で表現されます。

D(x,y,\sigma) = (G(x,y,k\sigma) - G(x,y,\sigma)) * I(x,y)

ここで、

  • G(x,y,\sigma) はガウシアンカーネル (標準偏差 \sigma のガウス分布)
  • I(x,y) は入力画像
  • k はスケール係数 (スケール空間を生成するためのパラメータ)

です。つまり、DoGは、異なるスケールのガウシアンぼかし画像の差分を計算することで、画像内のエッジやコーナーなどの特徴を強調します。

KAZE

KAZEは、非線形スケールスペースを使用して特徴点を検出します。従来のガウシアンスケールスペースと異なり、エッジ情報を保持しながらノイズを除去できる特徴があります。

非線形拡散フィルタリングは以下の式で表現されます。

\frac{\partial L}{\partial t} = \text{div}(c(x,y,t) \cdot \nabla L)

ここで、

  • L は輝度 (画像におけるピクセルの明るさ)
  • c は伝導係数 (拡散の速さを制御するパラメータ)
  • t は時間(スケール)パラメータ

です。伝導係数 c は、画像のエッジ部分で小さくなるように設計されており、これによりエッジをぼかすことなくノイズを除去できます。

AKAZE (Accelerated-KAZE)

AKAZEは、KAZEの高速版として開発されました。高速な非線形スケールスペース(FED: Fast Explicit Diffusion)を使用することで、KAZEと同等の性能を維持しながら、処理速度を大幅に向上させています。

ORB (Oriented FAST and Rotated BRIEF)

ORBは、FAST(Features from Accelerated Segment Test)とBRIEF(Binary Robust Independent Elementary Features)を組み合わせた手法です。FASTで検出した特徴点に対して、回転不変性を持たせるための改良を加えています。

  • FAST:高速なコーナー検出
  • BRIEF:バイナリ記述子による効率的な特徴量表現
  • 回転不変性の付加
  • 計算効率の良さ

BRISK (Binary Robust Invariant Scalable Keypoints)

BRISKは、スケール空間でのキーポイント検出とバイナリ記述子を組み合わせた手法です。サンプリングパターンを同心円状に配置することで、効率的な特徴量計算を実現しています。

FREAK (Fast Retina Keypoint)

FREAKは、人間の網膜の仕組みを模倣したサンプリングパターンを使用する特徴量記述子です。FASTディテクタと組み合わせて使用され、効率的な特徴点検出と記述を実現します。人間の視覚システムに着想を得たこのアプローチは、特に自然な画像において優れた性能を発揮します。

実装

ここでは、各アルゴリズムのOpenCVを用いたPythonによる実装例を示します。

import cv2
import numpy as np

def detect_features(image, algorithm, n_features=500):
    """
    指定されたアルゴリズムを使用して画像から特徴点を検出する。

    Args:
        image (np.ndarray): 入力画像 (BGR形式)。
        algorithm (str): 使用するアルゴリズムの名前 ('SIFT', 'KAZE', 'AKAZE', 'ORB', 'BRISK', 'FREAK')。
        n_features (int, optional): 検出する特徴点の最大数 (ORB, SIFTに適用)。デフォルトは500。

    Returns:
        tuple: (結果画像, キーポイント, 記述子)
    """
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    result = image.copy()

    if algorithm == 'SIFT':
        sift = cv2.SIFT_create(nfeatures=n_features)
        keypoints, descriptors = sift.detectAndCompute(gray, None)
    elif algorithm == 'KAZE':
        kaze = cv2.KAZE_create()
        keypoints, descriptors = kaze.detectAndCompute(gray, None)
    elif algorithm == 'AKAZE':
        akaze = cv2.AKAZE_create()
        keypoints, descriptors = akaze.detectAndCompute(gray, None)
    elif algorithm == 'ORB':
        orb = cv2.ORB_create(nfeatures=n_features)
        keypoints, descriptors = orb.detectAndCompute(gray, None)
    elif algorithm == 'BRISK':
        brisk = cv2.BRISK_create()
        keypoints, descriptors = brisk.detectAndCompute(gray, None)
    elif algorithm == 'FREAK':
        fast = cv2.FastFeatureDetector_create()
        keypoints = fast.detect(gray, None)
        freak = cv2.xfeatures2d.FREAK_create()
        keypoints, descriptors = freak.compute(gray, keypoints)
    else:
        raise ValueError("無効なアルゴリズム名です。")

    if keypoints:
        result = cv2.drawKeypoints(result, keypoints, result, color=(0, 255, 0), flags=0)

    return result, keypoints, descriptors

# 各アルゴリズムを試す
if __name__ == '__main__':
    # テスト画像の読み込み (例: 'image.jpg')
    test_image = cv2.imread('image.jpg')
    if test_image is None:
        print("画像の読み込みに失敗しました。")
        exit()

    algorithms = ['SIFT', 'KAZE', 'AKAZE', 'ORB', 'BRISK', 'FREAK']

    for algo in algorithms:
        try:
            detected_image, keypoints, descriptors = detect_features(test_image, algo)
            if keypoints:
                print(f"{algo}: {len(keypoints)}個の特徴点を検出")
                cv2.imshow(f'{algo} Feature Detection', detected_image)
            else:
                print(f"{algo}: 特徴点は検出されませんでした")
        except Exception as e:
            print(f"{algo}でエラーが発生しました: {e}")

    cv2.waitKey(0)
    cv2.destroyAllWindows()

このコードでは、各アルゴリズムを使用して特徴点を検出しています。OpenCVの関数cv2.drawKeypointsを用いることで、検出された特徴点を画像上に描画できます。

各アルゴリズムの実装におけるポイントは以下の通りです。

  • SIFT:n_features パラメータで検出する特徴点の最大数を制限できます。
  • KAZE:非線形スケールスペースを用いた特徴点検出を行います。
  • AKAZE:KAZEの高速版として実装されています。
  • ORB:FASTベースの検出器とBRIEFベースの記述子を組み合わせています。n_features パラメータで検出する特徴点の最大数を制限できます。
  • BRISK:スケール不変なキーポイント検出とバイナリ記述子を提供します。
  • FREAK:FASTディテクタと組み合わせて使用し、レチナサンプリングパターンによる特徴量記述を行います。

これらの実装を参考に、自身のアプリケーションに合わせたカスタマイズを行うことができます。

実験結果

各アルゴリズムを実際の画像に適用して比較を行いました。以下が結果です。mean_euclidean_distance / mean_hamming_distanceは、記述子の平均ユークリッド距離 / 平均ハミング距離です。この数値が大きいほど、記述子間をよく区別できていることを意味し、マッチングの精度が高いことを示します。

検出された特徴点の数:
SIFT: 1325
KAZE: 1199
AKAZE: 1120
ORB: 500
BRISK: 2540
FREAK: 4088

特徴量記述子の統計情報:

SIFT:
  type: 浮動小数点記述子
  dimension: 128
  mean_euclidean_distance: 535.435541714496

KAZE:
  type: 浮動小数点記述子
  dimension: 64
  mean_euclidean_distance: 0.815855450914292

AKAZE:
  type: バイナリ記述子
  dimension: 61
  mean_hamming_distance: 219.85932114132515

ORB:
  type: バイナリ記述子
  dimension: 32
  mean_hamming_distance: 123.53995991983967

BRISK:
  type: バイナリ記述子
  dimension: 64
  mean_hamming_distance: 236.3147283480073

FREAK:
  type: バイナリ記述子
  dimension: 64
  mean_hamming_distance: 222.01950830206223

特徴点の分布分析

各アルゴリズムで検出された特徴点の分布を詳しく分析しました。

  • 空間分布:特徴点が画像上のどの位置に分布しているかを確認します。
  • レスポンス強度:特徴点としての確からしさをカラーマップで表示します。
  • 特徴点のスケール:特徴点の大きさ(スケール)を点の大きさで表現します。






まとめ

本記事では、代表的な特徴点検出アルゴリズムの実装と特性比較を行いました。

用途に応じて適切なアルゴリズムを選択することが重要です。

  • 高精度なマッチングが必要な場合:SIFT
  • エッジ情報の保持が重要な場合:KAZE/AKAZE
  • 高速な処理が必要な場合:ORB/BRISK
  • メモリ効率が重要な場合:FREAK

これらのアルゴリズムは単体で使用されるだけでなく、画像の位置合わせや物体追跡など、より高度なコンピュータビジョンタスクの基礎となっており、様々な応用が可能です。

近年では、深層学習を用いた特徴点検出も盛んに行われています。例えば、SuperPointやD2-Netといった手法は、従来のSIFTやORBといった特徴点検出器を上回る性能を示すことが報告されています。これらの手法は、自己教師あり学習や教師あり学習を用いて学習されており、特定のタスクに最適化された特徴量を抽出することができます。

お気軽にご相談ください!

弊社のデジタル技術を活用し、貴社のDXをサポートします。

基本的な設計や実装支援はもちろん、機械学習・データ分析・3D計算などの高度な技術が求められる場面でも、最適なソリューションをご提案します。

初回相談は無料で受け付けております。困っていること、是非お聞かせください。