7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【図解】「深層学習不要」の最強アルゴリズムSIFTを、完全に理解する【Python/OpenCV】

Posted at

はじめに:人間には簡単、コンピュータには激ムズ?

突然ですが、以下の写真を見てください。
これらが「同じ風景」や「同じ猫」であることは、私たち人間なら一瞬で分かりますよね。

image.png
image.png

しかし、これをコンピュータに判別させるとなると、話は別です。
画像処理の世界では、以下のような変化が大きな障壁となります。

  • スケール(大きさ)が違う
  • 回転している
  • 明るさ(照明)が違う
  • 同じ対象でもピクセル単位で等しくない

image.png

これらを乗り越えて、画像の中から「変わらない特徴」を見つけ出す技術。それが今回紹介する SIFT(Scale-Invariant Feature Transform) です。

image.png

この記事では、大学のゼミで作成した講義スライドをベースに、SIFTの仕組みと実装方法を分かりやすく解説します。

全スライドまとめ

本記事のベースとなったスライド資料はこちらです。

1. SIFT(Scale-Invariant Feature Transform)とは?

image.png

SIFTは、画像のスケール、回転、明るさの変化に影響されずに、画像中の特徴点(キーポイント)を検出・記述するアルゴリズムです。

ディープラーニングが流行する前は、物体認識や画像合成の「王様」のような存在でした。現在でも、学習データが用意できない場合や、計算資源が限られる環境では非常に強力な選択肢です。

SIFTのすごいところ

SIFTが画期的だったのは、以下の「堅牢性(Robustness)」を兼ね備えていた点です。

特徴 説明
スケール不変性 対象の大きさが変わっても特徴量は変化しない
回転不変性 対象が回転しても大丈夫
照明変化への堅牢性 明るさやコントラストが変わっても認識可能

2. Python + OpenCVで3分実装

理屈の前に、まずは動かしてみましょう。
SIFTはかつて特許の壁がありましたが、現在は特許が切れ、OpenCVの標準機能として誰でも手軽に使えます。

import cv2 as cv

# 1. 画像の読み込み
img = cv.imread('cake.jpg')
gray = cv.cvtColor(img, cv.COLOR_BGR2GRAY)

# 2. SIFTオブジェクトの作成
sift = cv.SIFT_create()

# 3. 特徴点の検出と特徴量の計算
# kp: 特徴点のリスト, des: 特徴量記述子(128次元のベクトル)
kp, des = sift.detectAndCompute(gray, None)

# 4. 結果の描画
img_sift = cv.drawKeypoints(
    img, kp, None, 
    flags=cv.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS
)

# 表示(Colab等の場合)
# from google.colab.patches import cv2_imshow
# cv2_imshow(img_sift) 

image.png

たったこれだけのコードで、画像から堅牢な特徴点を抽出できます。

3. SIFTの仕組み:なぜそんなに強いのか?

ここからは、SIFTがどのようにして「回転しても、大きさが変わっても大丈夫」な特徴量を作り出しているのか、そのアルゴリズムを4つのステップで図解します。

全体像

SIFTの処理は大きく分けて 「特徴点の検出」「特徴量の記述」 の2段階、細かく見ると以下の4ステップになります。

  1. 候補点の探索(スケール空間の極値検出)
  2. 候補点の絞り込み(キーポイントのローカライズ)
  3. 方向の検出(オリエンテーションの割り当て)
  4. 特徴量の記述(記述子の生成)

image.png
image.png
image.png
image.png

ここからは各ステップを詳しく見ていきます。

Step 1: 候補点の探索(スケール不変性の獲得)

画像の中から「特徴的な点」を探す工程ですが、SIFTの最大の特徴は 「わざと画像をぼかして、様々なスケールの画像を用意する」 点にあります。

具体的には、DoG (Difference of Gaussian) 画像というものを作ります。
これは、「少しぼかした画像」と「もっとぼかした画像」の差分をとった画像です。こうすることで、エッジなどの変化が激しい部分が浮かび上がります。

image.png

これを様々なスケール(ぼかし具合)で行い、その中で極値(周囲と比べて際立って値が大きい/小さい点) を探します。
これによって、「遠くから見ても(小さいスケール)」、「近くで見ても(大きいスケール)」特徴的である場所を見つけ出すことができます。これがスケール不変性の正体です。

image.png
image.png
image.png

Step 2: 候補点の絞り込み

Step 1で見つかった点には、ノイズや、特徴としては弱い「エッジ(線)上の点」も含まれています。
そこで、ヘッセ行列という数学的な道具を使って、コーナー(角)のように 「縦横どちらの方向に動かしても変化が大きい点」 だけを厳選して残します。

image.png

💡 深掘り:なぜ「ヘッセ行列」でエッジとコーナーが見分けられるのか?

SIFTのアルゴリズムの中で、数学的に最も面白いのがこの「絞り込み」のプロセスです。ここを直感的に理解するために、視点を少し変えてみましょう。

「画像を2次元の平面ではなく、輝度を高さ(標高)と見立てた3次元の地形として捉える」 のです。

1. 画像を「地形」として見る

まず、以下の図を見てください。明るい画素を「高い山」、暗い画素を「低い谷」としてプロットすると、画像はこのようなデコボコした地形になります。

Gemini_Generated_Image_ug6jovug6jovug6j.jpg
図:輝度(Brightness)を地形の高さ(Height)として可視化したイメージ

SIFTにおける「特徴点探し」とは、この広大な地形の中から、「他と区別しやすい特別な場所(ランドマーク)」 を見つける旅のようなものです。

そのために使われるヘッセ行列は、足元の地面が「どの方向に、どれくらい曲がっているか(曲率)」を教えてくれるコンパスの役割を果たします。ここから得られる2つの固有値(曲がり具合の強さ)を見ることで、足元の形状が分かります。

2. エッジ(Edge)=「かまぼこ型の屋根」

エッジ上の点は、立体的には「かまぼこ型の屋根」や「トンネル」のような形状をしています。

Gemini_Generated_Image_590i8e590i8e590i.jpg
図:エッジのモデル図。一方は急勾配だが、もう一方は平坦

図の矢印に注目してください。

  • 🟥 赤い矢印(STEEP CURVE): 横方向には急激に曲がっています(=固有値 $\alpha$ が大きい)。
  • 🟦 青い矢印(FLAT DIRECTION): しかし、尾根に沿った縦方向は真っ平らです(=固有値 $\beta$ が小さい)。

この場所に立った時、青い矢印の方向に少し移動しても、景色(数値)はほとんど変わりません。つまり、「位置ズレに弱い(どこにいるか特定しにくい)」 のです。
そのため、SIFTはこの点を「不安定」とみなして削除します。

3. コーナー(Corner)=「尖った山頂」

一方、SIFTが探し求めているコーナーは、「尖った山頂」のような形状です。

Gemini_Generated_Image_j6mg5xj6mg5xj6mg.jpg
図:コーナーのモデル図。どの方向に降りようとしても急勾配

こちらも矢印を見てみましょう。

  • 🟥 赤い矢印(STEEP SLOPE): どの方向に降りようとしても、急な坂になっています。

これは、2つの固有値が共に大きい($\alpha$ も $\beta$ も大きい) 状態です。
この場所に立てば、どの方向に少し動いても景色が劇的に変わります。つまり、「位置を一点に特定しやすい」 ということです。

SIFTはヘッセ行列を使ってこの「山頂」のような形状だけを厳選することで、ノイズや位置ズレに負けない強固な特徴点を抽出しているのです。

Step 3: 方向の検出(回転不変性の獲得)

特徴点の場所が決まったら、その点が「どっちを向いているか」を決めます。
特徴点の周囲の画素を見て、勾配(明るさの変化方向)を集計します。最も強い勾配の方向を、その特徴点の 「主方向」 として定義します。

この後、画像を回転させても、この「主方向」を基準に特徴量を記述すれば、回転の影響をキャンセルできるわけです。

image.png

Step 4: 特徴量の記述(128次元ベクトル)

最後に、特徴点の特徴を数値化(ベクトル化)します。
特徴点の周囲を16個のブロック(4×4)に分け、それぞれのブロックで8方向の勾配情報を集計します。

$$4 \times 4 \times 8 = 128$$

これにより、1つの特徴点は128次元のベクトルとして表現されます。これがSIFT特徴量です。
この際、光の強さの影響を受けないように正規化を行うことで、照明変化への堅牢性も獲得しています。

image.png

4. まとめ:SIFTの強さの秘密

SIFTがなぜこれほどまでに使い勝手が良いのか、各ステップがどのように堅牢性に寄与しているかをまとめました。

堅牢性の種類 実現しているステップ 理由
スケール不変性 Step 1 DoG画像を用いて適切なスケールを探索しているから
回転不変性 Step 3, 4 特徴点の「主方向」を基準に記述しているから
照明変化への堅牢性 Step 4 勾配情報を正規化しているから
ノイズ・ズレへの堅牢性 Step 2, 4 不安定な点を除去し、情報を大まかに(ヒストグラム化)集計しているから

深層学習全盛の時代ですが、学習データ不要で、数行のコードでこれだけ堅牢な特徴抽出ができるSIFTは、現在でも非常に強力なツールです。

ぜひ、皆さんの画像処理アプリケーションでも活用してみてください!

参考文献

資料作成の際に、こちらの資料を大変参考にさせていただきました。ありがとうございます。

7
9
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?