Python で OpenCV を使用した SIFT

Manav Narula 2023年10月10日
  1. 特徴抽出のためのSIFTアルゴリズム
  2. SIFT クラスを使用して、Python で OpenCV を使用して SIFT を実装する
  3. Python で OpenCV を使用して SIFT アルゴリズムを実装して 2つの画像を一致させる
  4. まとめ
Python で OpenCV を使用した SIFT

特徴抽出は、画像処理と機械学習に不可欠なプロセスです。 貴重な情報を抽出することにより、生データを情報に変換することを指します。

画像処理では、有効なキー ポイントとその記述子を見つけます。

Python では、OpenCV ライブラリを使用して画像を処理および操作します。 このライブラリを使用して、さまざまな手法と事前定義されたアルゴリズムを適用できます。

このチュートリアルでは、OpenCV を使用して SIFT アルゴリズムを実装し、それを Python での特徴マッチングに使用する方法を示します。 また、Python で OpenCV を使用して SIFT アルゴリズムを使用して 2つの画像を照合する方法も学習します。

特徴抽出のためのSIFTアルゴリズム

SIFT (Scale Invariant Feature Transform) は、複雑で役立つ特徴抽出手法です。 これは、回転バリアントまたはスケールバリアントである可能性がある他のアルゴリズムの問題を克服します。つまり、画像が回転する または異なるサイズにスケーリングされると、抽出される情報が変化する可能性があります。

SIFT アルゴリズムは、有効なキー ポイントとその記述子を抽出することで、これらすべてを回避します。 スケールおよび回転不変です。

特徴抽出についてはすでに説明しました。 ここで、特徴抽出のための SIFT アルゴリズムに含まれる手順について説明します。

ステージは全部で5つ。

スケール空間の極値検出

最初の段階は、スケール空間の極値検出と呼ばれます。

説明したように、あらゆる規模に存在する機能が必要です。 より大きなスケールでは、より大きなウィンドウが必要です。

この段階では、異なるスケーリング パラメータを使用し、ガウスの差、つまりさまざまなスケーリング パラメータ値によるガウスぼかしの差を計算します。 指定されたスケーリング値を使用して座標を選択し、より高いスケーリング値とより低いスケーリング値で座標が存在するかどうかを確認します。

キーポイント ローカリゼーション

次に、キーポイントのローカリゼーションであるステージ 2 に進みましょう。 このステージでは、選択したキー ポイントを除外します。

スケールのテイラー級数展開を使用して、より洗練された重要なポイントを取得し、それらの強度を見つけます。 強度が指定されたしきい値未満の場合、拒否されます。

オリエンテーションの割り当て

次の段階は、オリエンテーションの割り当てと呼ばれます。 説明したように、重要なポイントは回転不変であり、この段階でも同じことが保証されます。

勾配とその方向を計算するために、キー ポイントの周囲の領域が使用されます。 360 度を表す 36 個のビンが作成され、ヒストグラムにプロットされます。80% を超えるピークは新しいキー ポイントと見なされ、選択したキーポイントの方向を決定するために使用されます。

キーポイント記述子

第 4 段階は、キーポイントに隣接する 16x16 ブロックを取得し、それを 4x4 の 16 ブロックに分割することによって、キーポイント記述子を作成することを目的としています。 8つのビンを含むブロックごとに方向ヒストグラムが作成されます。

これらの値はすべて、キーポイント記述子ベクトルとして表されます。

キーポイントマッチング

最終段階では、キーポイント マッチングが行われます。 2つのキー ポイントを、それらの近傍を見つけることによって一致させます。

これは、誤った一致を排除するために使用されます。

ここまで、SIFT アルゴリズムについて詳しく説明してきました。 Python の OpenCV ライブラリを使用してこれを実装する方法を見てみましょう。

SIFT クラスを使用して、Python で OpenCV を使用して SIFT を実装する

SIFT_create() コンストラクター オブジェクトを使用して、画像からキー ポイントを検出できる SIFT クラスのオブジェクトを作成できます。

すべてのパラメーターにはデフォルト値がありますが、さまざまなパラメーターを指定できます。 パラメータは、nfeaturesnOctaveLayerscontrastThresholdedgeThresholdsigma、および descriptorType です。

nfeatures パラメーターは、結果から選択する最適な機能の数を指定できます。 各オクターブのレイヤーは、デフォルトが 3 の nOctaveLayers パラメータを使用して指定できます。

contrastThresholdedgeThreshold の値は、弱いエッジのような特徴を除外します。 Gaussian のシグマは、sigma パラメータを使用して指定されます。これは、ソフト レンズでクリックされた画像に対して下げることができます。

最後のパラメーターは、CV_32F または CV_8U のいずれかである記述子のタイプを指定します。

このメソッドの使用方法を見てみましょう。

import numpy as np
import cv2 as cv

i = cv.imread("obj.png")
g = cv.cvtColor(i, cv.COLOR_BGR2GRAY)

sift_ob = cv.SIFT_create()
kp = sift_ob.detect(g, None)
img = cv.drawKeypoints(g, kp, i)

cv.imshow("Output", img)
cv.waitKey(0)
cv.destroyAllWindows()

出力:

OpenCV Python で SIFT を使用してキーポイントを検出および描画する

上記の例を理解してみましょう。

imread() 関数を使用して画像を読み取ります。 次に、任意の画像の色空間を変更できる cvtColor メソッドを使用して、この画像をグレースケールに変換しました。

このアルゴリズムは、グレースケール イメージでうまく機能します。

SIFT_create() 関数をデフォルト値で使用してオブジェクトを作成しました。 作成されたオブジェクトで detect() 関数を使用して、指定された画像内のポイントを識別します。 結果を格納するタプルを返します。

drawKeypoints() 関数を使用して、より視覚的に表現しやすくするために、画像にキー ポイントを描画します。 この関数でタプルと画像を渡します。

最終的な画像は、imshow() 関数を使用して表示されます。

waitKey() 関数は、ユーザーが何らかのキーを押すのを待って、出力ウィンドウが自動的に閉じるのを防ぎました。 destroyAllWindows() 関数を使用してウィンドウを閉じました。

SIFT は以前 OpenCV Contrib ライブラリに存在し、2020 年に特許が切れたときに OpenCV に追加されました。OpenCV バージョン 3.4.2.16 では使用できなくなりました。

Python で OpenCV を使用して SIFT アルゴリズムを実装することにより、2つの画像を一致させる方法について説明します。

Python で OpenCV を使用して SIFT アルゴリズムを実装して 2つの画像を一致させる

上記で説明したように、SIFT アルゴリズムを使用して、さまざまなキー ポイントと記述子を検出できます。 このために、ブルートフォースマッチャーを使用できます。

ブルートフォース マッチャーは、一度に 1つのキーポイントとその記述子を取得し、それを別の画像の一連の特徴と照合して、最も近い一致を返します。

そのため、BFMatcher() コンストラクターを使用してブルート フォース マッチャー オブジェクトを作成します。 このオブジェクトは 2つのパラメーターを受け入れます。

最初のパラメーターは normType パラメーターで、使用される距離です。 文字列ベースの場合、NORM_HAMMING を使用する必要がありますが、今回のケース (SIFT) では、NORM_L1 または NORM_l2 を使用できます。

2 番目のパラメーターは crossCheck で、True に設定すると、いずれかのセットで対応する一致のみが返されます。 BFMatcher オブジェクトを作成した後、match() 関数を使用して、マッチングのために記述子の 2つのセットを渡すことができます。

この後、drawMatches() 関数を使用して、2つの画像にそれぞれの一致を描画できます。 画像を並べて配置し、一致したキーポイントを線で結合します。

各ラインには、フィーチャを識別するための固有の色があります。 この例を見てみましょう。

クトゥブ・ミナールの次の 2つの画像の特徴を一致させます。

画像 1:

照合する画像1

画像 2:

照合する画像2

コード:

import cv2
import matplotlib.pyplot as plt

# %matplotlib inline

i1 = cv2.imread("q3.jpeg")
i2 = cv2.imread("q4.jpeg")

img1 = cv2.cvtColor(i1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(i2, cv2.COLOR_BGR2GRAY)

sift = cv2.SIFT_create()

k_1, des_1 = sift.detectAndCompute(img1, None)
k_2, des_2 = sift.detectAndCompute(img2, None)

bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)

matches = bf.match(des_1, des_2)
matches = sorted(matches, key=lambda x: x.distance)

img3 = cv2.drawMatches(img1, k_1, img2, k_2, matches[:50], img2, flags=2)
cv2.imshow("Output", img3)
cv2.waitKey(0)
cv2.destroyAllWindows()

出力:

Python OpenCV で SIFT を使用した画像特徴マッチング

上記の例では、SIFT アルゴリズムとブルート フォース マッチャーを使用して 2つの画像の特徴を照合しました。

まず、SIFT アルゴリズムを使用して 2つの画像の特徴を抽出しました。 次に、Brute-Force マッチャー オブジェクトを使用してこれらの機能を照合しました。

結果の一致は、drawMatches() 関数を使用して両方の画像に描画されました。

まとめ

このチュートリアルでは、Python で OpenCV を使用して特徴抽出のための SIFT アルゴリズムを実装する方法を示しました。 SIFT アルゴリズムの背後にある理論が詳細に説明され、他の手法に対する利点が強調されました。

このアルゴリズムの 5つの段階について詳しく説明しました。 これらは、スケール スペース極値検出、キーポイント ローカリゼーション、方向割り当て、キーポイント記述子、およびキーポイント マッチングでした。

SIFT_create() オブジェクトを使用して SIFT クラスのオブジェクトを作成することにより、この手法を実装することについて説明しました。 このクラスの detect() メソッドの使用を強調し、drawKeypoints() 関数を使用してキー ポイントを描画しました。

また、Python で OpenCV を使用して SIFT アルゴリズムを使用して 2つの画像を照合する方法についても説明しました。 このために、まず、SIFT アルゴリズムを使用して特徴を抽出しました。 次に、Brute-Force マッチャーのオブジェクトを作成しました。

オブジェクトの match() 属性に記述子を渡して、一致を見つけました。 結果は、drawMatches() 関数を使用して視覚的に表現するために、両方の画像に描画されました。

著者: Manav Narula
Manav Narula avatar Manav Narula avatar

Manav is a IT Professional who has a lot of experience as a core developer in many live projects. He is an avid learner who enjoys learning new things and sharing his findings whenever possible.

LinkedIn

関連記事 - Python OpenCV