PythonでOpenCVを使用したSIFT特徴抽出

SIFTはScaleInvariant Feature Transformの略で、画像コンテンツが変換、スケール、およびその他の画像変換に対して不変であるローカル特徴座標に変換される特徴抽出方法です(HOG特徴抽出など)。

このチュートリアルでは、SIFTの背後にある理論と、OpenCVライブラリを使用してPythonでSIFTを実装する方法を学習します。

SIFTの利点は次のとおりです。

  • ローカリティ:機能はローカルです。閉塞や乱雑さに強い。
  • 特徴:抽出された個々の特徴は、オブジェクトの大規模なデータセットと照合できます。
  • 数量:SIFTを使用すると、小さなオブジェクトから多くの特徴を抽出できます。
  • 効率:SIFTはリアルタイムのパフォーマンスに近いです。

SIFTの概要は次のとおりです。

  1. スケール空間極値検出:同じシーンまたはオブジェクトの異なるビューの下で繰り返し割り当てることができる場所とスケールを識別します。
  2. キーポイントのローカリゼーション:モデルを適合させて特徴の位置とスケールを決定し、安定性の尺度に基づいてキーポイントを選択します。
  3. 方向の割り当て:各キーポイント領域の最適な方向を計算します。
  4. キーポイントの説明:選択したスケールと回転でローカル画像のグラデーションを使用して、各キーポイント領域を説明します。

スケールスペース極値検出

最初のステップでは、同じオブジェクトまたはシーンの異なるビューの下で繰り返し割り当てることができる場所とスケールを特定します。識別のために、ガウス関数を使用したスケールの連続関数を使用して、複数のスケールにわたって安定した特徴を検索します。

画像のスケール空間は、入力画像とのガウスカーネル(異なるスケール)の畳み込みから生成される関数L(x、y、a)です。

各オクターブで、初期画像はガウス分布で繰り返し畳み込まれ、一連のスケール空間画像が生成されます。各レベルで、画像は滑らかになり、サイズが縮小されます。各オクターブの後、ガウス画像は2倍にダウンサンプリングされ、次のレベルを開始するために1/4のサイズの画像が生成されます。隣接するガウスが減算されて、DoG(ガウスの差)が生成されます。

最初のオクターブを作成するために、シグマの値が異なる入力画像にガウスフィルターが適用され、次に2番目以降のオクターブに対して、画像が最初に2倍にダウンサンプリングされ、次に値が異なるガウスフィルターが適用されます。

シグマ値は次のとおりです。

  • オクターブ1はσのスケールを使用します。
  • オクターブ2は2σのスケールを使用します。
  • 等々。

次の画像は4オクターブを示し、各オクターブには6つの画像が含まれています。

4オクターブ

オクターブあたりの音階数について質問がありますか?調査によると、オクターブごとに4つのスケールが必要です。

オクターブあたりのスケール数

次に、オクターブ内の2つの連続する画像が差し引かれ、ガウスの差が得られます。

ガウスの違い

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

ガウスの差をとった後、現在および隣接するスケールの26ピクセルとピクセル(x)を比較することにより、スケール空間の最大値と最小値を検出する必要があります。各ポイントは、現在の画像の8つの隣接点と、上下のスケールでそれぞれ9つの隣接点と比較されます。

規模

以下は、サンプル画像で見つかった極値ポイントです。

極値ポイント

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

方向の割り当ては、回転の不変性を実現するために行われます。勾配の大きさと方向の計算は、ガウスぼかし画像のキーポイント周辺の隣接領域のすべてのピクセルに対して実行されます。

大きさはピクセルの強度を表し、方向は同じ方向を示します。

勾配の大きさに使用される式は次のとおりです。

グラデーション式

方向計算の式は次のとおりです。

方向の公式

次に、各ポイントの方向を確認する必要があります。重みも方向に割り当てられます。下の青い四角の矢印は約90度の角度で、その長さはそれがどれだけ重要かを示しています。

各ポイントの方向

ヒストグラムは、方向を36のビンに量子化することによって形成され、各ビンは10度をカバーします。ヒストグラムには、特定の角度を持つピクセルの数が表示されます。たとえば、36度の角度を持つピクセルはいくつありますか?

特定の角度のヒストグラムピクセル

キーポイントの説明

この時点で、各キーポイントには場所、スケール、方向があります。次に 、キーポイントの周りの正規化された領域を使用する必要がある記述子を計算する必要があります。まず、キーポイントの周りに16×16の近隣を取ります。この16×16ブロックはさらに4×4サブブロックに分割され、これらのサブブロックごとに、大きさと方向を使用してヒストグラムが生成されます。

画像勾配

128次元の1つの長いベクトルに16個のヒストグラムを連結します。4x4 x 8方向は、128個の値のベクトルを提供します。

Pythonの実装

これで、SIFTの背後にある理論を理解できたと思います。次に、OpenCVを使用してPythonコードについて詳しく見ていきましょう。まず、SIFTを実装するOpenCVの特定のバージョンをインストールしましょう。

pip3 install numpy opencv-python==3.4.2.16 opencv-contrib-python==3.4.2.16

新しいPythonファイルを開いて、それに従ってください。特定の本を含むこのテーブルを操作します(ここで入手してください)。

import cv2 

# reading the image
img = cv2.imread('table.jpg')
# convert to greyscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

上記のコードは画像をロードしてグレースケールに変換します。SIFT特徴抽出オブジェクトを作成しましょう。

# create SIFT feature extractor
sift = cv2.xfeatures2d.SIFT_create()

キーポイントと記述子を検出するには、画像をdetectAndCompute()メソッドに渡すだけです。

# detect features from the image
keypoints, descriptors = sift.detectAndCompute(img, None)

最後に、キーポイントを描画し、画像を表示して保存しましょう。

# draw the detected key points
sift_image = cv2.drawKeypoints(gray, keypoints, img)
# show the image
cv2.imshow('image', sift_image)
# save the image
cv2.imwrite("table-sift.jpg", sift_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果の画像は次のとおりです。

検出されたキーポイント

これらのSIFT機能ポイントは、多くのユースケースで役立ちます。以下にいくつかを示します。

このデモンストレーションで実際に使用するために、機能のマッチングを選択します。OpenCVを使用して、同じオブジェクトの2つの画像を異なる角度からマッチングします(画像はこのGithubリポジトリで取得できます)。

import cv2

# read the images
img1 = cv2.imread('book.jpg')  
img2 = cv2.imread('table.jpg')
# convert images to grayscale
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# create SIFT object
sift = cv2.xfeatures2d.SIFT_create()
# detect SIFT features in both images
keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)
keypoints_2, descriptors_2 = sift.detectAndCompute(img2,None)

両方の画像のキーポイントと記述子ができたので、記述子に一致するマッチャーを作成しましょう。

# create feature matcher
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
# match descriptors of both images
matches = bf.match(descriptors_1,descriptors_2)

マッチを距離で並べ替えて、最初の50のマッチを描きましょう。

# sort matches by distance
matches = sorted(matches, key = lambda x:x.distance)
# draw first 50 matches
matched_img = cv2.drawMatches(img1, keypoints_1, img2, keypoints_2, matches[:50], img2, flags=2)

最後に、画像を表示して保存します。

# show the image
cv2.imshow('image', matched_img)
# save the image
cv2.imwrite("matched_images.jpg", matched_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

出力:

一致した画像

結論

了解しました。このチュートリアルでは、SIFTの基本について説明しました。詳細については、元の論文を読むことをお勧めします。

また、OpenCVはcv2.xfeatures2d.SIFT_create()メソッドでSIFTのデフォルトパラメータを使用し、保持する機能の数を変更できます(nfeaturesnOctaveLayerssigmaなど。help(cv2.xfeatures2d.SIFT_create)詳細については、入力してください。

リンク: https://www.thepythoncode.com/article/sift-feature-extraction-using-opencv-in-python

#python 

 

What is GEEK

Buddha Community

PythonでOpenCVを使用したSIFT特徴抽出

PythonでOpenCVを使用したSIFT特徴抽出

SIFTはScaleInvariant Feature Transformの略で、画像コンテンツが変換、スケール、およびその他の画像変換に対して不変であるローカル特徴座標に変換される特徴抽出方法です(HOG特徴抽出など)。

このチュートリアルでは、SIFTの背後にある理論と、OpenCVライブラリを使用してPythonでSIFTを実装する方法を学習します。

SIFTの利点は次のとおりです。

  • ローカリティ:機能はローカルです。閉塞や乱雑さに強い。
  • 特徴:抽出された個々の特徴は、オブジェクトの大規模なデータセットと照合できます。
  • 数量:SIFTを使用すると、小さなオブジェクトから多くの特徴を抽出できます。
  • 効率:SIFTはリアルタイムのパフォーマンスに近いです。

SIFTの概要は次のとおりです。

  1. スケール空間極値検出:同じシーンまたはオブジェクトの異なるビューの下で繰り返し割り当てることができる場所とスケールを識別します。
  2. キーポイントのローカリゼーション:モデルを適合させて特徴の位置とスケールを決定し、安定性の尺度に基づいてキーポイントを選択します。
  3. 方向の割り当て:各キーポイント領域の最適な方向を計算します。
  4. キーポイントの説明:選択したスケールと回転でローカル画像のグラデーションを使用して、各キーポイント領域を説明します。

スケールスペース極値検出

最初のステップでは、同じオブジェクトまたはシーンの異なるビューの下で繰り返し割り当てることができる場所とスケールを特定します。識別のために、ガウス関数を使用したスケールの連続関数を使用して、複数のスケールにわたって安定した特徴を検索します。

画像のスケール空間は、入力画像とのガウスカーネル(異なるスケール)の畳み込みから生成される関数L(x、y、a)です。

各オクターブで、初期画像はガウス分布で繰り返し畳み込まれ、一連のスケール空間画像が生成されます。各レベルで、画像は滑らかになり、サイズが縮小されます。各オクターブの後、ガウス画像は2倍にダウンサンプリングされ、次のレベルを開始するために1/4のサイズの画像が生成されます。隣接するガウスが減算されて、DoG(ガウスの差)が生成されます。

最初のオクターブを作成するために、シグマの値が異なる入力画像にガウスフィルターが適用され、次に2番目以降のオクターブに対して、画像が最初に2倍にダウンサンプリングされ、次に値が異なるガウスフィルターが適用されます。

シグマ値は次のとおりです。

  • オクターブ1はσのスケールを使用します。
  • オクターブ2は2σのスケールを使用します。
  • 等々。

次の画像は4オクターブを示し、各オクターブには6つの画像が含まれています。

4オクターブ

オクターブあたりの音階数について質問がありますか?調査によると、オクターブごとに4つのスケールが必要です。

オクターブあたりのスケール数

次に、オクターブ内の2つの連続する画像が差し引かれ、ガウスの差が得られます。

ガウスの違い

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

ガウスの差をとった後、現在および隣接するスケールの26ピクセルとピクセル(x)を比較することにより、スケール空間の最大値と最小値を検出する必要があります。各ポイントは、現在の画像の8つの隣接点と、上下のスケールでそれぞれ9つの隣接点と比較されます。

規模

以下は、サンプル画像で見つかった極値ポイントです。

極値ポイント

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

方向の割り当ては、回転の不変性を実現するために行われます。勾配の大きさと方向の計算は、ガウスぼかし画像のキーポイント周辺の隣接領域のすべてのピクセルに対して実行されます。

大きさはピクセルの強度を表し、方向は同じ方向を示します。

勾配の大きさに使用される式は次のとおりです。

グラデーション式

方向計算の式は次のとおりです。

方向の公式

次に、各ポイントの方向を確認する必要があります。重みも方向に割り当てられます。下の青い四角の矢印は約90度の角度で、その長さはそれがどれだけ重要かを示しています。

各ポイントの方向

ヒストグラムは、方向を36のビンに量子化することによって形成され、各ビンは10度をカバーします。ヒストグラムには、特定の角度を持つピクセルの数が表示されます。たとえば、36度の角度を持つピクセルはいくつありますか?

特定の角度のヒストグラムピクセル

キーポイントの説明

この時点で、各キーポイントには場所、スケール、方向があります。次に 、キーポイントの周りの正規化された領域を使用する必要がある記述子を計算する必要があります。まず、キーポイントの周りに16×16の近隣を取ります。この16×16ブロックはさらに4×4サブブロックに分割され、これらのサブブロックごとに、大きさと方向を使用してヒストグラムが生成されます。

画像勾配

128次元の1つの長いベクトルに16個のヒストグラムを連結します。4x4 x 8方向は、128個の値のベクトルを提供します。

Pythonの実装

これで、SIFTの背後にある理論を理解できたと思います。次に、OpenCVを使用してPythonコードについて詳しく見ていきましょう。まず、SIFTを実装するOpenCVの特定のバージョンをインストールしましょう。

pip3 install numpy opencv-python==3.4.2.16 opencv-contrib-python==3.4.2.16

新しいPythonファイルを開いて、それに従ってください。特定の本を含むこのテーブルを操作します(ここで入手してください)。

import cv2 

# reading the image
img = cv2.imread('table.jpg')
# convert to greyscale
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

上記のコードは画像をロードしてグレースケールに変換します。SIFT特徴抽出オブジェクトを作成しましょう。

# create SIFT feature extractor
sift = cv2.xfeatures2d.SIFT_create()

キーポイントと記述子を検出するには、画像をdetectAndCompute()メソッドに渡すだけです。

# detect features from the image
keypoints, descriptors = sift.detectAndCompute(img, None)

最後に、キーポイントを描画し、画像を表示して保存しましょう。

# draw the detected key points
sift_image = cv2.drawKeypoints(gray, keypoints, img)
# show the image
cv2.imshow('image', sift_image)
# save the image
cv2.imwrite("table-sift.jpg", sift_image)
cv2.waitKey(0)
cv2.destroyAllWindows()

結果の画像は次のとおりです。

検出されたキーポイント

これらのSIFT機能ポイントは、多くのユースケースで役立ちます。以下にいくつかを示します。

このデモンストレーションで実際に使用するために、機能のマッチングを選択します。OpenCVを使用して、同じオブジェクトの2つの画像を異なる角度からマッチングします(画像はこのGithubリポジトリで取得できます)。

import cv2

# read the images
img1 = cv2.imread('book.jpg')  
img2 = cv2.imread('table.jpg')
# convert images to grayscale
img1 = cv2.cvtColor(img1, cv2.COLOR_BGR2GRAY)
img2 = cv2.cvtColor(img2, cv2.COLOR_BGR2GRAY)
# create SIFT object
sift = cv2.xfeatures2d.SIFT_create()
# detect SIFT features in both images
keypoints_1, descriptors_1 = sift.detectAndCompute(img1,None)
keypoints_2, descriptors_2 = sift.detectAndCompute(img2,None)

両方の画像のキーポイントと記述子ができたので、記述子に一致するマッチャーを作成しましょう。

# create feature matcher
bf = cv2.BFMatcher(cv2.NORM_L1, crossCheck=True)
# match descriptors of both images
matches = bf.match(descriptors_1,descriptors_2)

マッチを距離で並べ替えて、最初の50のマッチを描きましょう。

# sort matches by distance
matches = sorted(matches, key = lambda x:x.distance)
# draw first 50 matches
matched_img = cv2.drawMatches(img1, keypoints_1, img2, keypoints_2, matches[:50], img2, flags=2)

最後に、画像を表示して保存します。

# show the image
cv2.imshow('image', matched_img)
# save the image
cv2.imwrite("matched_images.jpg", matched_img)
cv2.waitKey(0)
cv2.destroyAllWindows()

出力:

一致した画像

結論

了解しました。このチュートリアルでは、SIFTの基本について説明しました。詳細については、元の論文を読むことをお勧めします。

また、OpenCVはcv2.xfeatures2d.SIFT_create()メソッドでSIFTのデフォルトパラメータを使用し、保持する機能の数を変更できます(nfeaturesnOctaveLayerssigmaなど。help(cv2.xfeatures2d.SIFT_create)詳細については、入力してください。

リンク: https://www.thepythoncode.com/article/sift-feature-extraction-using-opencv-in-python

#python